Esempio n. 1
0
File: lua.c Progetto: benlaurie/ldns
static int
l_pkt_push_rr(lua_State *L)
{
	ldns_pkt *pkt = (ldns_pkt*)lua_touserdata(L, 1); /* get the packet */
	ldns_pkt_section s = (ldns_pkt_section)lua_tonumber(L, 2); /* the section where to put it */
	ldns_rr *rr = (ldns_rr*)lua_touserdata(L, 3); /* the rr to put */

	if (!pkt) {
		return 0;
	}

	if (ldns_pkt_push_rr(pkt, s, rr)) {
		lua_pushlightuserdata(L, pkt);
		return 1;
	} else {
		return 0;
	}
}
Esempio n. 2
0
int
main(int argc, char **argv)
{
	int c;
	int i;

	/* LDNS types */
	ldns_pkt *notify;
	ldns_rr *question;
	ldns_resolver *res;
	ldns_rdf *ldns_zone_name = NULL;
	ldns_status status;
	const char *zone_name = NULL;
	int include_soa = 0;
	uint32_t soa_version = 0;
	ldns_tsig_credentials tsig_cred = {0,0,0};
	int do_hexdump = 1;
	uint8_t *wire = NULL;
	size_t wiresize = 0;
	char *port = "53";

	srandom(time(NULL) ^ getpid());

        while ((c = getopt(argc, argv, "vhdp:r:s:y:z:")) != -1) {
                switch (c) {
                case 'd':
			verbose++;
			break;
                case 'p':
			port = optarg;
			break;
                case 'r':
			max_num_retry = atoi(optarg);
			break;
                case 's':
			include_soa = 1;
			soa_version = (uint32_t)atoi(optarg);
			break;
                case 'y':
			tsig_cred.algorithm = "hmac-md5.sig-alg.reg.int.";
			tsig_cred.keyname = optarg;
			tsig_cred.keydata = strchr(optarg, ':');
			*tsig_cred.keydata = '\0';
			tsig_cred.keydata++;
			printf("Sign with %s : %s\n", tsig_cred.keyname,
				tsig_cred.keydata);
			break;
                case 'z':
			zone_name = optarg;
			ldns_zone_name = ldns_dname_new_frm_str(zone_name);
			if(!ldns_zone_name) {
				printf("cannot parse zone name: %s\n", 
					zone_name);
				exit(1);
			}
                        break;
		case 'v':
			version();
                case 'h':
                case '?':
                default:
                        usage();
                }
        }
        argc -= optind;
        argv += optind;

        if (argc == 0 || zone_name == NULL) {
                usage();
        }

	notify = ldns_pkt_new();
	question = ldns_rr_new();
	res = ldns_resolver_new();

	if (!notify || !question || !res) {
		/* bail out */
		printf("error: cannot create ldns types\n");
		exit(1);
	}

	/* create the rr for inside the pkt */
	ldns_rr_set_class(question, LDNS_RR_CLASS_IN);
	ldns_rr_set_owner(question, ldns_zone_name);
	ldns_rr_set_type(question, LDNS_RR_TYPE_SOA);
	ldns_pkt_set_opcode(notify, LDNS_PACKET_NOTIFY);
	ldns_pkt_push_rr(notify, LDNS_SECTION_QUESTION, question);
	ldns_pkt_set_aa(notify, true);
	ldns_pkt_set_id(notify, random()&0xffff);
	if(include_soa) {
		char buf[10240];
		ldns_rr *soa_rr=NULL;
		ldns_rdf *prev=NULL;
		snprintf(buf, sizeof(buf), "%s 3600 IN SOA . . %u 0 0 0 0",
			zone_name, (unsigned)soa_version);
		/*printf("Adding soa %s\n", buf);*/
		status = ldns_rr_new_frm_str(&soa_rr, buf, 3600, NULL, &prev);
		if(status != LDNS_STATUS_OK) {
			printf("Error adding SOA version: %s\n",
				ldns_get_errorstr_by_id(status));
		}
		ldns_pkt_push_rr(notify, LDNS_SECTION_ANSWER, soa_rr);
	}

	if(tsig_cred.keyname) {
#ifdef HAVE_SSL
		status = ldns_pkt_tsig_sign(notify, tsig_cred.keyname,
			tsig_cred.keydata, 300, tsig_cred.algorithm,
			NULL);
		if(status != LDNS_STATUS_OK) {
			printf("Error TSIG sign query: %s\n",
				ldns_get_errorstr_by_id(status));
		}
#else
	fprintf(stderr, "Warning: TSIG needs OpenSSL support, which has not been compiled in, TSIG skipped\n");
#endif
	}

	if(verbose) {
		printf("# Sending packet:\n");
		ldns_pkt_print(stdout, notify);

	}

	status = ldns_pkt2wire(&wire, notify, &wiresize);
	if(wiresize == 0) {
		printf("Error converting notify packet to hex.\n");
		exit(1);
	}

	if(do_hexdump && verbose > 1) {
		printf("Hexdump of notify packet:\n");
		for(i=0; i<(int)wiresize; i++)
			printf("%02x", (unsigned)wire[i]);
		printf("\n");
	}

	for(i=0; i<argc; i++)
	{
		struct addrinfo hints, *res0, *res;
		int error;
		int default_family = AF_INET;

		if(verbose)
			printf("# sending to %s\n", argv[i]);
		memset(&hints, 0, sizeof(hints));
		hints.ai_family = default_family;
		hints.ai_socktype = SOCK_DGRAM;
		hints.ai_protocol = IPPROTO_UDP;
		error = getaddrinfo(argv[i], port, &hints, &res0);
		if (error) {
			printf("skipping bad address: %s: %s\n", argv[i],
				gai_strerror(error));
			continue;
		}
		for (res = res0; res; res = res->ai_next) {
			int s = socket(res->ai_family, res->ai_socktype, 
				res->ai_protocol);
			if(s == -1)
				continue;
			/* send the notify */
			notify_host(s, res, wire, wiresize, argv[i]);
		}
		freeaddrinfo(res0);
	}

	ldns_pkt_free(notify);
	free(wire);
        return 0;
}
Esempio n. 3
0
/* Reads one entry from file. Returns entry or NULL on error. */
struct entry*
read_entry(FILE* in, const char* name, int *lineno, uint32_t* default_ttl, 
	ldns_rdf** origin, ldns_rdf** prev_rr)
{
	struct entry* current = NULL;
	char line[MAX_LINE];
	char* parse;
	ldns_pkt_section add_section = LDNS_SECTION_QUESTION;
	struct reply_packet *cur_reply = NULL;
	bool reading_hex = false;
	ldns_buffer* hex_data_buffer = NULL;

	while(fgets(line, (int)sizeof(line), in) != NULL) {
		line[MAX_LINE-1] = 0;
		parse = line;
		(*lineno) ++;
		
		while(isspace((int)*parse))
			parse++;
		/* test for keywords */
		if(isendline(*parse))
			continue; /* skip comment and empty lines */
		if(str_keyword(&parse, "ENTRY_BEGIN")) {
			if(current) {
				error("%s line %d: previous entry does not ENTRY_END", 
					name, *lineno);
			}
			current = new_entry();
			current->lineno = *lineno;
			cur_reply = entry_add_reply(current);
			continue;
		} else if(str_keyword(&parse, "$ORIGIN")) {
			get_origin(name, *lineno, origin, parse);
			continue;
		} else if(str_keyword(&parse, "$TTL")) {
			*default_ttl = (uint32_t)atoi(parse);
			continue;
		}

		/* working inside an entry */
		if(!current) {
			error("%s line %d: expected ENTRY_BEGIN but got %s", 
				name, *lineno, line);
		}
		if(str_keyword(&parse, "MATCH")) {
			matchline(parse, current);
		} else if(str_keyword(&parse, "REPLY")) {
			replyline(parse, cur_reply->reply);
		} else if(str_keyword(&parse, "ADJUST")) {
			adjustline(parse, current, cur_reply);
		} else if(str_keyword(&parse, "EXTRA_PACKET")) {
			cur_reply = entry_add_reply(current);
		} else if(str_keyword(&parse, "SECTION")) {
			if(str_keyword(&parse, "QUESTION"))
				add_section = LDNS_SECTION_QUESTION;
			else if(str_keyword(&parse, "ANSWER"))
				add_section = LDNS_SECTION_ANSWER;
			else if(str_keyword(&parse, "AUTHORITY"))
				add_section = LDNS_SECTION_AUTHORITY;
			else if(str_keyword(&parse, "ADDITIONAL"))
				add_section = LDNS_SECTION_ADDITIONAL;
			else error("%s line %d: bad section %s", name, *lineno, parse);
		} else if(str_keyword(&parse, "HEX_ANSWER_BEGIN")) {
			hex_data_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
			reading_hex = true;
		} else if(str_keyword(&parse, "HEX_ANSWER_END")) {
			if (!reading_hex) {
				error("%s line %d: HEX_ANSWER_END read but no HEX_ANSWER_BEGIN keyword seen", name, *lineno);
			}
			reading_hex = false;
			cur_reply->reply_from_hex = data_buffer2wire(hex_data_buffer);
			ldns_buffer_free(hex_data_buffer);
		} else if(str_keyword(&parse, "ENTRY_END")) {
			return current;
		} else if(reading_hex) {
			ldns_buffer_printf(hex_data_buffer, line);
		} else {
			/* it must be a RR, parse and add to packet. */
			ldns_rr* n = NULL;
			ldns_status status;
			if(add_section == LDNS_SECTION_QUESTION)
				status = ldns_rr_new_question_frm_str(
					&n, parse, *origin, prev_rr);
			else status = ldns_rr_new_frm_str(&n, parse, 
				*default_ttl, *origin, prev_rr);
			if(status != LDNS_STATUS_OK)
				error("%s line %d:\n\t%s: %s", name, *lineno,
					ldns_get_errorstr_by_id(status), parse);
			ldns_pkt_push_rr(cur_reply->reply, add_section, n);
		}

	}
	if (reading_hex) {
		error("%s: End of file reached while still reading hex, "
			"missing HEX_ANSWER_END\n", name);
	}
	if(current) {
		error("%s: End of file reached while reading entry. "
			"missing ENTRY_END\n", name);
	}
	return 0;
}
Esempio n. 4
0
int
main(int argc, char **argv)
{
	/* arguments */
	int port;
	int soa;
	ldns_rdf *zone_name;
	size_t count;
	size_t maxcount;

	/* network */
	int sock;
	ssize_t nb;
	struct sockaddr addr_me;
	struct sockaddr addr_him;
	socklen_t hislen = sizeof(addr_him);
	const char *my_address;
	uint8_t inbuf[INBUF_SIZE];
	uint8_t *outbuf;

	/* dns */
	ldns_status status;
	ldns_pkt *query_pkt;
	ldns_pkt *answer_pkt;
	size_t answer_size;
	ldns_rr *query_rr;
	ldns_rr *rr;
	char rr_string[MAX_LEN + 1];
	ldns_rr *soa_rr;
	char soa_string[MAX_LEN + 1];
	
	/* use this to listen on specified interfaces later? */
	my_address = NULL;

	if(argc == 5) {
		/* -# num given */
		if (argv[1][0] == '-') {
			maxcount = atoi(argv[1] + 1);
			if (maxcount == 0) {
				usage(stdout);
				exit(EXIT_FAILURE);
			} else {
				fprintf(stderr, "quiting after %d qs\n", (int)maxcount);
			}
		} else {
			fprintf(stderr, "Use -Number for max count\n");
			exit(EXIT_FAILURE);
		}
		argc--;
		argv++;
	} else {
		maxcount = 0;
	}
	
	if (argc != 4) {
		usage(stdout);
		exit(EXIT_FAILURE);
	} else {
		port = atoi(argv[1]);
		if (port < 1) {
			fprintf(stderr, "Use a number for the port\n");
			usage(stdout);
			exit(EXIT_FAILURE);
		}
		
		zone_name = ldns_dname_new_frm_str(argv[2]);
		if (!zone_name) {
			fprintf(stderr, "Illegal domain name: %s\n", argv[2]);
			usage(stdout);
			exit(EXIT_FAILURE);
		}
		soa =  atoi(argv[3]);
		if (soa < 1) {
			fprintf(stderr, "Illegal soa number\n");
			usage(stdout);
			exit(EXIT_FAILURE);
		}
			
	}
	
	printf("Listening on port %d\n", port);
	sock =  socket(AF_INET, SOCK_DGRAM, 0);
	if (sock < 0) {
		fprintf(stderr, "%s: socket(): %s\n", argv[0], strerror(errno));
		exit(EXIT_FAILURE);
	}

	memset(&addr_me, 0, sizeof(addr_me));

	/* bind: try all ports in that range */
	if (udp_bind(sock, port, my_address)) {
		fprintf(stderr, "%s: cannot bind(): %s\n", argv[0], strerror(errno));
	}

	/* create our ixfr answer */
	answer_pkt = ldns_pkt_new();

	snprintf(rr_string, MAX_LEN, "%s IN IXFR", argv[2]);
	(void)ldns_rr_new_frm_str(&rr, rr_string , 0, NULL, NULL);
	(void)ldns_pkt_push_rr(answer_pkt, LDNS_SECTION_QUESTION, rr);

	 /* next add some rrs, with SOA stuff so that we mimic or ixfr reply */
	snprintf(soa_string, MAX_LEN, "%s IN SOA miek.miek.nl elektron.atoom.net %d 1 2 3000 4",
			argv[2], soa);

        (void)ldns_rr_new_frm_str(&soa_rr, soa_string, 0, NULL, NULL);
	snprintf(rr_string, MAX_LEN, "%s IN A 127.0.0.1", argv[2]);
        (void)ldns_rr_new_frm_str(&rr, rr_string , 0, NULL, NULL);

        /* compose the ixfr pkt */
        (void)ldns_pkt_push_rr(answer_pkt, LDNS_SECTION_ANSWER, soa_rr);
        (void)ldns_pkt_push_rr(answer_pkt, LDNS_SECTION_ANSWER, rr);
        (void)ldns_pkt_push_rr(answer_pkt, LDNS_SECTION_ANSWER, soa_rr);

	/* Done. Now receive */
	count = 0;
	while (1) {
		nb = recvfrom(sock, inbuf, INBUF_SIZE, 0, &addr_him, &hislen);
		if (nb < 1) {
			fprintf(stderr, "%s: recvfrom(): %s\n",
				argv[0], strerror(errno));
			exit(EXIT_FAILURE);
		}
		
		printf("Got query of %d bytes\n", (int)nb);
		status = ldns_wire2pkt(&query_pkt, inbuf, nb);
		if (status != LDNS_STATUS_OK) {
			printf("Got bad packet: %s\n", ldns_get_errorstr_by_id(status));
			continue;
		}
		
		query_rr = ldns_rr_list_rr(ldns_pkt_question(query_pkt), 0);
		printf("%d QUERY RR +%d: \n", (int)++count, ldns_pkt_id(query_pkt));
		ldns_rr_print(stdout, query_rr);
		
		ldns_pkt_set_id(answer_pkt, ldns_pkt_id(query_pkt));

		status = ldns_pkt2wire(&outbuf, answer_pkt, &answer_size);
		
		printf("Answer packet size: %u bytes.\n", (unsigned int) answer_size);
		if (status != LDNS_STATUS_OK) {
			printf("Error creating answer: %s\n", ldns_get_errorstr_by_id(status));
		} else {
			nb = (size_t) sendto(sock, outbuf, answer_size, 0, &addr_him, hislen);
		}

		if (maxcount > 0  && count >= maxcount) {
			fprintf(stderr, "%d queries seen... goodbye\n", (int)count);
			exit(EXIT_SUCCESS);
		}
	}
        return 0;
}