if (addr->sa_family == AF_UNSPEC) {
return;
}
+ if (s->outgoing) {
+ assert(s->peer.ip.sa_family != AF_UNSPEC);
+ if (kr_sockaddr_cmp(&s->peer.ip, addr) != 0) {
+ return;
+ }
+ }
knot_pkt_t *query = knot_pkt_new(buf->base, nread, &worker->pkt_pool);
if (query) {
query->max_size = KNOT_WIRE_MAX_PKTSIZE;
return ret;
}
ret = ioreq_spawn(task, SOCK_DGRAM, choice->sin6_family);
- if (ret &&
- qr_task_send(task, ret, (struct sockaddr *)choice,
+ if (!ret) {
+ return ret;
+ }
+ struct sockaddr *addr = (struct sockaddr *)choice;
+ struct session *session = ret->data;
+ assert (session->peer.ip.sa_family == AF_UNSPEC);
+ session->outgoing = true;
+ memcpy(&session->peer, addr, sizeof(session->peer));
+ if (qr_task_send(task, ret, (struct sockaddr *)choice,
task->pktbuf) == 0) {
task->addrlist_turn = (task->addrlist_turn + 1) %
task->addrlist_count; /* Round robin */
}
}
+int kr_sockaddr_cmp(const struct sockaddr *left, const struct sockaddr *right)
+{
+ if (!left || !right) {
+ return kr_error(EINVAL);
+ }
+ if (left->sa_family != right->sa_family) {
+ return kr_error(EFAULT);
+ }
+ if (left->sa_family == AF_INET) {
+ struct sockaddr_in *left_in = (struct sockaddr_in *)left;
+ struct sockaddr_in *right_in = (struct sockaddr_in *)right;
+ if (left_in->sin_addr.s_addr != right_in->sin_addr.s_addr) {
+ return kr_error(EFAULT);
+ }
+ } else if (left->sa_family == AF_INET6) {
+ struct sockaddr_in6 *left_in6 = (struct sockaddr_in6 *)left;
+ struct sockaddr_in6 *right_in6 = (struct sockaddr_in6 *)right;
+ if (memcmp(&left_in6->sin6_addr, &right_in6->sin6_addr,
+ sizeof(struct in6_addr)) != 0) {
+ return kr_error(EFAULT);
+ }
+ } else {
+ return kr_error(ENOENT);
+ }
+ return kr_ok();
+}
+
uint16_t kr_inaddr_port(const struct sockaddr *addr)
{
if (!addr) {
/** Sockaddr length for given family, i.e. sizeof(struct sockaddr_in*). */
KR_EXPORT KR_PURE
int kr_sockaddr_len(const struct sockaddr *addr);
+/** Compare two given sockaddr.
+ * return 0 - addresses are equal, error code otherwise.
+ */
+KR_EXPORT KR_PURE
+int kr_sockaddr_cmp(const struct sockaddr *left, const struct sockaddr *right);
/** Port. */
KR_EXPORT KR_PURE
uint16_t kr_inaddr_port(const struct sockaddr *addr);