static int notify_check_and_schedule(knot_nameserver_t *nameserver, const knot_zone_t *zone, sockaddr_t *from) { if (zone == NULL || from == NULL || knot_zone_data(zone) == NULL) { return KNOT_EINVAL; } /* Check ACL for notify-in. */ zonedata_t *zd = (zonedata_t *)knot_zone_data(zone); if (from) { if (acl_match(zd->notify_in, from, 0) == ACL_DENY) { /* rfc1996: Ignore request and report incident. */ return KNOT_EDENIED; } } /* Cancel REFRESH/RETRY timer. */ evsched_t *sched = ((server_t *)knot_ns_get_data(nameserver))->sched; event_t *refresh_ev = zd->xfr_in.timer; if (refresh_ev) { dbg_notify("notify: expiring REFRESH timer\n"); evsched_cancel(sched, refresh_ev); /* Set REFRESH timer for now. */ evsched_schedule(sched, refresh_ev, 0); } return KNOT_EOK; }
static void* dbgs(void* arg) { EXPECT_EQ(0, sem_wait(&dbg_lock)); uint saved_lvl = fbi_get_debug(); fbi_set_debug(UINT_MAX); long unsigned exp_tid = (long unsigned) pthread_self(); long unsigned tid = 0; #define TID_SCAN_STR "%20lu%*[^\n]" dbg_critical("Test dbg"); EXPECT_EQ(1, fscanf(redir, TID_SCAN_STR, &tid)); EXPECT_EQ(exp_tid, tid); dbg_error("Test dbg"); EXPECT_EQ(1, fscanf(redir, TID_SCAN_STR, &tid)); EXPECT_EQ(exp_tid, tid); dbg_warning("Test dbg"); EXPECT_EQ(1, fscanf(redir, TID_SCAN_STR, &tid)); EXPECT_EQ(exp_tid, tid); dbg_notify("Test dbg"); EXPECT_EQ(1, fscanf(redir, TID_SCAN_STR, &tid)); EXPECT_EQ(exp_tid, tid); dbg_info("Test dbg"); EXPECT_EQ(1, fscanf(redir, TID_SCAN_STR, &tid)); EXPECT_EQ(exp_tid, tid); dbg_debug("Test dbg"); EXPECT_EQ(1, fscanf(redir, TID_SCAN_STR, &tid)); EXPECT_EQ(exp_tid, tid); dbg_spew("Test dbg"); EXPECT_EQ(1, fscanf(redir, TID_SCAN_STR, &tid)); EXPECT_EQ(exp_tid, tid); dbg_low("Test dbg"); EXPECT_EQ(1, fscanf(redir, TID_SCAN_STR, &tid)); EXPECT_EQ(exp_tid, tid); dbg_medium("Test dbg"); EXPECT_EQ(1, fscanf(redir, TID_SCAN_STR, &tid)); EXPECT_EQ(exp_tid, tid); dbg_high("Test dbg"); EXPECT_EQ(1, fscanf(redir, TID_SCAN_STR, &tid)); EXPECT_EQ(exp_tid, tid); fbi_set_debug(saved_lvl); EXPECT_EQ(0, sem_post(&dbg_lock)); return nullptr; }
int notify_create_response(knot_packet_t *request, uint8_t *buffer, size_t *size) { knot_packet_t *response = knot_packet_new(KNOT_PACKET_PREALLOC_QUERY); CHECK_ALLOC_LOG(response, KNOT_ENOMEM); /* Set maximum packet size. */ int rc = knot_packet_set_max_size(response, *size); if (rc == KNOT_EOK) { rc = knot_response_init_from_query(response, request, 1); } /* Aggregated result check. */ if (rc != KNOT_EOK) { dbg_notify("%s: failed to init response packet: %s", "notify_create_response", knot_strerror(rc)); knot_packet_free(&response); return KNOT_EINVAL; } // TODO: copy the SOA in Answer section uint8_t *wire = NULL; size_t wire_size = 0; rc = knot_packet_to_wire(response, &wire, &wire_size); if (rc != KNOT_EOK) { knot_packet_free(&response); return rc; } if (wire_size > *size) { knot_packet_free(&response); return KNOT_ESPACE; } memcpy(buffer, wire, wire_size); *size = wire_size; knot_packet_dump(response); knot_packet_free(&response); return KNOT_EOK; }
int notify_process_request(knot_nameserver_t *ns, knot_packet_t *notify, sockaddr_t *from, uint8_t *buffer, size_t *size) { /*! \todo Most of this function is identical to xfrin_transfer_needed() * - it will be fine to merge the code somehow. */ if (notify == NULL || ns == NULL || buffer == NULL || size == NULL || from == NULL) { dbg_notify("notify: invalid parameters for %s()\n", "notify_process_request"); return KNOT_EINVAL; } int ret = KNOT_EOK; dbg_notify("notify: parsing rest of the packet\n"); if (notify->parsed < notify->size) { if (knot_packet_parse_rest(notify, 0) != KNOT_EOK) { dbg_notify("notify: failed to parse NOTIFY query\n"); knot_ns_error_response_from_query(ns, notify, KNOT_RCODE_FORMERR, buffer, size); return KNOT_EOK; } } // check if it makes sense - if the QTYPE is SOA if (knot_packet_qtype(notify) != KNOT_RRTYPE_SOA) { // send back FORMERR knot_ns_error_response_from_query(ns, notify, KNOT_RCODE_FORMERR, buffer, size); return KNOT_EOK; } // create NOTIFY response dbg_notify("notify: creating response\n"); ret = notify_create_response(notify, buffer, size); if (ret != KNOT_EOK) { dbg_notify("notify: failed to create NOTIFY response\n"); knot_ns_error_response_from_query(ns, notify, KNOT_RCODE_SERVFAIL, buffer, size); return KNOT_EOK; } /* Process notification. */ ret = KNOT_ENOZONE; unsigned serial = 0; const knot_dname_t *qname = knot_packet_qname(notify); rcu_read_lock(); /* z */ const knot_zone_t *z = knot_zonedb_find_zone_for_name(ns->zone_db, qname); if (z != NULL) { ret = notify_check_and_schedule(ns, z, from); const knot_rrset_t *soa_rr = NULL; soa_rr = knot_packet_answer_rrset(notify, 0); if (soa_rr && knot_rrset_type(soa_rr) == KNOT_RRTYPE_SOA) { serial = knot_rrset_rdata_soa_serial(soa_rr); } } rcu_read_unlock(); int rcode = KNOT_RCODE_NOERROR; switch (ret) { case KNOT_ENOZONE: rcode = KNOT_RCODE_NOTAUTH; break; case KNOT_EACCES: rcode = KNOT_RCODE_REFUSED; break; default: break; } /* Format resulting log message. */ char *qstr = knot_dname_to_str(qname); char *fromstr = xfr_remote_str(from, NULL); if (rcode != KNOT_RCODE_NOERROR) { knot_ns_error_response_from_query(ns, notify, KNOT_RCODE_REFUSED, buffer, size); log_server_warning(NOTIFY_MSG "%s\n", qstr, fromstr, knot_strerror(ret)); ret = KNOT_EOK; /* Send response. */ } else { log_server_info(NOTIFY_MSG NOTIFY_XMSG "\n", qstr, fromstr, serial); } free(qstr); free(fromstr); return ret; }