Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members | Related Pages

Using the server library

In order for this to make sense, you should also have read Using the client library, since the server is built on top of that. Also, some knowledge of DNS RFC's 1034 and 1035 is highly recommended.

In order to be able to use the server library, you'll need to know a little about how it works. The server has one main function, serverthread(), which handles incoming data for the server. This function can be run directly from your program, by running posserver_run(), or in the background, by running posserver_startback(). Stopping the Posadis server can be done by pos_setquitflag().

If you want to make the server listen at interfaces, you'll need to add them to the servers list, declared in serverthread.h. You can do this both before starting the Posadis server, or while it is running. If you want to use the latter posibility though, you'll need to obtain a lock on the m_servers mutex.

For example, let's make Posadis listen to the DNS port, 53, on all interfaces:


  
try { _addr a; // the address structure txt_to_addr(&a, "0.0.0.0", DNS_PORT, false); // listen to all interfaces // start listning on both udp and tcp servers.push_front(ServerSocket(ss_udp, udpcreateserver(&a))); servers.push_front(ServerSocket(ss_tcp, tcpcreateserver(&a))); } catch (PException p) { printf("Error initializing servers: %s\n", p.message); }

  

Now that the server system is running, we'll want to be able to answer queries. Each query that is being received, is handled by the function the handle_query function pointer points to. So, by changing that pointer (before the server runs), we can provide our own answers to the queries we receive. For more information on how this works, consult the handle_query documentation.

Poslib has its own logging mechanism you can use. You will need to initialize it in order to be able to report error messages Posadis logs to your users. You can also use this logging function yourself by calling the pos_log function. See log.h for details.

This is a simple server that will only answer A queries for acdam.net. and www.acdam.net. As such, it isn't really useful except as an example.


  
// Use the default logging system #define POS_DEFAULTLOG #define POS_DEFAULTLOG_STDERR #define POS_DEFAULTLOG_SYSLOG // Server include file #include <poslib/server/server.h> // For signal handling //#include #include #include DnsMessage *my_handle_query(pending_query *query); void cleanup(int sig) { // close down the server system pos_setquitflag(); } int main(int argc, char **argv) { _addr a; try { /* get command-line arguments */ if (argc == 2 && argv[1][0] == '@') { txt_to_addr(&a, argv[1] + 1); } else { txt_to_addr(&a, "any"); // printf("Usage: server \n"); // return 1; } /* bring up posadis */ servers.push_front(ServerSocket(ss_udp, udpcreateserver(&a))); servers.push_front(ServerSocket(ss_tcp, tcpcreateserver(&a))); // use the posadis logging system pos_log(context_none, log_info, "Posadis example server starting up..."); // set signal handlers signal(SIGINT, cleanup); signal(SIGTERM, cleanup); // set query function handle_query = my_handle_query; // run server posserver_run(); } catch (PException p) { printf("Fatal exception: %s\n", p.message); return 1; } return 0; } /* the entry function which will handle all queries */ DnsMessage *my_handle_query(pending_query *query) { DnsMessage *a = new DnsMessage(); DnsQuestion q; DnsRR rr; /* set a as an answer to the query */ a->ID = query->message->ID; a->RD = query->message->RD; a->RA = false; if (query->message->questions.begin() == query->message->questions.end()) { /* query did not contain question */ a->RCODE = RCODE_QUERYERR; return a; } q = *query->message->questions.begin(); a->questions.push_back(q); a->QR = true; pos_log(context_server, log_info, "Query: [%s,%s]", q.QNAME.tocstr(), str_qtype(q.QTYPE).c_str()); if (q.QTYPE == DNS_TYPE_A && (q.QNAME == "acdam.net" || q.QNAME == "www.acdam.net")) { /* append address information */ rr = DnsRR(q.QNAME, DNS_TYPE_A, CLASS_IN, 3600); /* set RR data */ string data = rr_fromstring(DNS_TYPE_A, "192.168.1.1"); rr.RDLENGTH = data.size(); rr.RDATA = (char *)memdup(data.c_str(), data.size()); a->answers.push_back(rr); } else { /* we don't want this */ a->RCODE = RCODE_SRVFAIL; } return a; }

  

  
00001 // Use the default logging system 00002 #define POS_DEFAULTLOG 00003 #define POS_DEFAULTLOG_STDERR 00004 #define POS_DEFAULTLOG_SYSLOG 00005 00006 // Server include file 00007 #include <poslib/server/server.h> 00008 00009 // For signal handling 00010 //#include 00011 #include 00012 #include 00013 00014 DnsMessage *my_handle_query(pending_query *query); 00015 00016 void cleanup(int sig) { 00017 // close down the server system 00018 pos_setquitflag(); 00019 } 00020 00021 int main(int argc, char **argv) { 00022 _addr a; 00023 00024 try { 00025 /* get command-line arguments */ 00026 if (argc == 2 && argv[1][0] == '@') { 00027 txt_to_addr(&a, argv[1] + 1); 00028 } else { 00029 txt_to_addr(&a, "any"); 00030 // printf("Usage: server \n"); 00031 // return 1; 00032 } 00033 00034 /* bring up posadis */ 00035 servers.push_front(ServerSocket(ss_udp, udpcreateserver(&a))); 00036 servers.push_front(ServerSocket(ss_tcp, tcpcreateserver(&a))); 00037 00038 // use the posadis logging system 00039 pos_log(context_none, log_info, "Posadis example server starting up..."); 00040 00041 // set signal handlers 00042 signal(SIGINT, cleanup); 00043 signal(SIGTERM, cleanup); 00044 00045 // set query function 00046 00047 handle_query = my_handle_query; 00048 00049 // run server 00050 posserver_run(); 00051 } catch (PException p) { 00052 printf("Fatal exception: %s\n", p.message); 00053 return 1; 00054 } 00055 00056 return 0; 00057 } 00058 00059 /* the entry function which will handle all queries */ 00060 DnsMessage *my_handle_query(pending_query *query) { 00061 DnsMessage *a = new DnsMessage(); 00062 DnsQuestion q; 00063 DnsRR rr; 00064 00065 /* set a as an answer to the query */ 00066 a->ID = query->message->ID; 00067 a->RD = query->message->RD; 00068 a->RA = false; 00069 00070 if (query->message->questions.begin() == query->message->questions.end()) { 00071 /* query did not contain question */ 00072 a->RCODE = RCODE_QUERYERR; 00073 return a; 00074 } 00075 q = *query->message->questions.begin(); 00076 a->questions.push_back(q); 00077 a->QR = true; 00078 00079 pos_log(context_server, log_info, "Query: [%s,%s]", q.QNAME.tocstr(), str_qtype(q.QTYPE).c_str()); 00080 00081 if (q.QTYPE == DNS_TYPE_A && (q.QNAME == "acdam.net" || q.QNAME == "www.acdam.net")) { 00082 /* append address information */ 00083 rr = DnsRR(q.QNAME, DNS_TYPE_A, CLASS_IN, 3600); 00084 /* set RR data */ 00085 string data = rr_fromstring(DNS_TYPE_A, "192.168.1.1"); 00086 rr.RDLENGTH = data.size(); 00087 rr.RDATA = (char *)memdup(data.c_str(), data.size()); 00088 a->answers.push_back(rr); 00089 } else { 00090 /* we don't want this */ 00091 a->RCODE = RCODE_SRVFAIL; 00092 } 00093 return a; 00094 }

  

And if we compile it like this:


  
g++ `poslib-config --libs --cflags --server` server.cpp -o server
And run it like this:
  

  
./server
We've got ourself a DNS server running at port 3000.
  
Generated on Fri Dec 24 19:55:17 2004 for Poslib by doxygen 1.3.7