2. Making a small application with ldns

In this tutorial we will make a small application which takes a domain name and looks up the MX records for this domain. We will call this program: 'mx'.

The general flow of the program is as follows:

  1. make a resolver structure,

  2. use the resolver to generate an mx query,

  3. print the result.

First we begin with some boiler plating:


      1 /*
      2  * mx is a small programs that prints out the mx records
      3  * for a particulary domain
      4  */
      5
      6 #include <stdio.h>
      7 
      8 #include <ldns/dns.h>
      9
     10 int
     11 usage(FILE *fp, char *prog) {
     12         fprintf(fp, "%s zone\n", prog);
     13         fprintf(fp, "  print out the mx for the domain\n");
     14         return 0;
     15 }
     16
Line 9 is the important one here, this includes all the stuff we need from ldns.

     17 int
     18 main(int argc, char *argv[])
     19 {
     20         ldns_resolver *res;
     21         ldns_rdf *domain;
     22         ldns_pkt *p;
     23         ldns_rr_list *mx;
     24
     25
     26         if (argc != 2) {
     27                 usage(stdout, argv[0]);
     28                 exit(1);
     29         } else {
     30                 /* create a rdf from the command line arg */
     31                 domain = ldns_dname_new_frm_str(argv[1]);
     32                 if (!domain) {
     33                         usage(stdout, argv[0]);
     34                         exit(1);
     35                 }
     36                 /* transform it in a string for the error msg (if needed) */
     38         }
Here we parse the arguments. We create a new rdf structure which contain the domain name that we got from the commandline.

     39
     40         /* create a new resolver from /etc/resolv.conf */
     41         res = ldns_resolver_new_frm_file(NULL);
     42         if (!res) {
     43			exit(1);
     44         }
At line 41 we create a new resolver structure. When it's argument is NULL it uses /etc/resolv.conf to setup the resolver structure.

     45         
     46
     47         /* use the resolver to send it a query for the mx
     48          * records of the domain given on the command line
     49          */
     50         p = ldns_resolver_query(res, domain, LDNS_RR_TYPE_MX, LDNS_RR_CLASS_IN, LDNS_RD);
At line 50 we do the actual query. The ldns_resolver_query command returns ldns_pkt* structure, with the reply from the nameserver. As we look at the function call, we see that we do a query for a RR type 'MX' in the class 'IN' and we set the RD (recursion desired) flag on the qeury.

     51         if (!p)  {
     52
     53                 exit(1);
     54         } else {
     55                 /* retrieve the MX records from the answer section of that
     56                  * packet
     57                  */
     58                 mx = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_MX, LDNS_SECTION_ANSWER);
On line 58 we look inside the packet to see if we got any MX records back for our query. We look only inside the answer section of the packet.

     59                 if (!mx) {
     60                         fprintf(stderr,
     61                                         " *** invalid answer name %s after MX query for %s\n        ",
     62                                         argv[1],
     63                                         argv[1]);
     64                         exit(1);
     65                 } else {
     66                         /* sort the list nicely */
     67                         ldns_rr_list_sort(mx);
     68                         /* print the rrlist to stdout */
     69                         ldns_rr_list_print(stdout, mx);
     70                 }
Here we sort the list and print it to stdout.

     71         }
     72         return 0;
     73 }

This example shows that with a fairly short C program you can already do complex tasks.