diff --git a/include/re_dns.h b/include/re_dns.h index ad25c75..6e1465e 100644 --- a/include/re_dns.h +++ b/include/re_dns.h @@ -195,7 +195,6 @@ struct dnsc_conf { uint32_t tcp_hash_size; uint32_t conn_timeout; /* in [ms] */ uint32_t idle_timeout; /* in [ms] */ - bool udp_conn; }; int dnsc_alloc(struct dnsc **dcpp, const struct dnsc_conf *conf, diff --git a/include/re_udp.h b/include/re_udp.h index 426fc19..e9cdcd1 100644 --- a/include/re_udp.h +++ b/include/re_udp.h @@ -17,11 +17,12 @@ struct udp_sock; * @param arg Handler argument */ typedef void (udp_recv_h)(const struct sa *src, struct mbuf *mb, void *arg); +typedef void (udp_error_h)(int err, void *arg); int udp_listen(struct udp_sock **usp, const struct sa *local, udp_recv_h *rh, void *arg); -void udp_connect(struct udp_sock *us, bool conn); +int udp_connect(struct udp_sock *us, const struct sa *peer); int udp_send(struct udp_sock *us, const struct sa *dst, struct mbuf *mb); int udp_send_anon(const struct sa *dst, struct mbuf *mb); int udp_local_get(const struct udp_sock *us, struct sa *local); @@ -31,6 +32,7 @@ int udp_sockbuf_set(struct udp_sock *us, int size); void udp_rxsz_set(struct udp_sock *us, size_t rxsz); void udp_rxbuf_presz_set(struct udp_sock *us, size_t rx_presz); void udp_handler_set(struct udp_sock *us, udp_recv_h *rh, void *arg); +void udp_error_handler_set(struct udp_sock *us, udp_error_h *eh); int udp_thread_attach(struct udp_sock *us); void udp_thread_detach(struct udp_sock *us); int udp_sock_fd(const struct udp_sock *us, int af); diff --git a/src/dns/client.c b/src/dns/client.c index 95688c7..3e5a1b2 100644 --- a/src/dns/client.c +++ b/src/dns/client.c @@ -91,7 +91,6 @@ static const struct dnsc_conf default_conf = { TCP_HASH_SIZE, CONN_TIMEOUT, IDLE_TIMEOUT, - false }; @@ -861,14 +860,6 @@ int dnsc_alloc(struct dnsc **dcpp, const struct dnsc_conf *conf, if (err) goto out; - /* Experimental code: - * Connected UDP sockets will only work if we have one UDP socket - * per UDP server. Connected UDP socket is used to get ICMP - * messages for unreachable DNS Servers. - */ - if (dnsc->conf.udp_conn) - udp_connect(dnsc->us, true); - err = hash_alloc(&dnsc->ht_query, dnsc->conf.query_hash_size); if (err) goto out; diff --git a/src/udp/udp.c b/src/udp/udp.c index 490710d..d238ef8 100644 --- a/src/udp/udp.c +++ b/src/udp/udp.c @@ -63,13 +63,13 @@ enum { struct udp_sock { struct list helpers; /**< List of UDP Helpers */ udp_recv_h *rh; /**< Receive handler */ + udp_error_h *eh; /**< Error handler */ void *arg; /**< Handler argument */ int fd; /**< Socket file descriptor */ int fd6; /**< IPv6 socket file descriptor */ bool conn; /**< Connected socket flag */ size_t rxsz; /**< Maximum receive chunk size */ size_t rx_presz; /**< Preallocated rx buffer size */ - int err; /**< Cached error code */ }; /** Defines a UDP helper */ @@ -195,9 +195,8 @@ static void udp_read(struct udp_sock *us, int fd) goto out; } #endif - - /* cache error code */ - us->err = err; + if (us->eh) + us->eh(err, us->arg); goto out; } @@ -396,18 +395,33 @@ int udp_listen(struct udp_sock **usp, const struct sa *local, /** - * Connect a UDP Socket to its peer, so we can receive ICMP messages. + * Connect a UDP Socket to a specific peer. * When connected, this UDP Socket will only receive data from that peer. * * @param us UDP Socket - * @param conn Connected flag + * @param peer Peer network address + * + * @return 0 if success, otherwise errorcode */ -void udp_connect(struct udp_sock *us, bool conn) +int udp_connect(struct udp_sock *us, const struct sa *peer) { - if (!us) - return; + int fd; - us->conn = conn; + if (!us || !peer) + return EINVAL; + + /* choose a socket */ + if (AF_INET6 == sa_af(peer) && -1 != us->fd6) + fd = us->fd6; + else + fd = us->fd; + + if (0 != connect(fd, &peer->u.sa, peer->len)) + return errno; + + us->conn = true; + + return 0; } @@ -417,13 +431,6 @@ static int udp_send_internal(struct udp_sock *us, const struct sa *dst, struct sa hdst; int err = 0, fd; - /* check for error in e.g. connected state */ - if (us->err) { - err = us->err; - us->err = 0; /* clear error */ - return err; - } - /* choose a socket */ if (AF_INET6 == sa_af(dst) && -1 != us->fd6) fd = us->fd6; @@ -447,11 +454,6 @@ static int udp_send_internal(struct udp_sock *us, const struct sa *dst, /* Connected socket? */ if (us->conn) { - if (0 != connect(fd, &dst->u.sa, dst->len)) { - DEBUG_WARNING("send: connect: %m\n", errno); - us->conn = false; - } - if (send(fd, BUF_CAST mb->buf + mb->pos, mb->end - mb->pos, 0) < 0) return errno; @@ -642,6 +644,21 @@ void udp_handler_set(struct udp_sock *us, udp_recv_h *rh, void *arg) } +/** + * Set error handler on a UDP Socket + * + * @param us UDP Socket + * @param eh Error handler + */ +void udp_error_handler_set(struct udp_sock *us, udp_error_h *eh) +{ + if (!us) + return; + + us->eh = eh; +} + + /** * Get the File Descriptor from a UDP Socket *