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:
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.
#define POS_DEFAULTLOG #define POS_DEFAULTLOG_STDERR #define POS_DEFAULTLOG_SYSLOG #include <poslib/server/server.h> #include #include DnsMessage *my_handle_query(
pending_query *query);
void cleanup(
int sig) {
pos_setquitflag(); }
int main(
int argc,
char **argv) {
_addr a;
try {
if (argc == 2 && argv[1][0] ==
'@') {
txt_to_addr(&a, argv[1] + 1); }
else {
txt_to_addr(&a,
"any"); } servers.push_front(
ServerSocket(ss_udp,
udpcreateserver(&a))); servers.push_front(
ServerSocket(ss_tcp,
tcpcreateserver(&a)));
pos_log(context_none, log_info,
"Posadis example server starting up..."); signal(SIGINT, cleanup); signal(SIGTERM, cleanup);
handle_query = my_handle_query;
posserver_run(); }
catch (
PException p) { printf(
"Fatal exception: %s\n", p.message);
return 1; }
return 0; }
DnsMessage *my_handle_query(
pending_query *query) {
DnsMessage *a =
new DnsMessage();
DnsQuestion q;
DnsRR rr; a->
ID = query->
message->
ID; a->
RD = query->
message->
RD; a->
RA =
false;
if (query->
message->questions.begin() == query->
message->questions.end()) { 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")) { rr =
DnsRR(q.
QNAME, DNS_TYPE_A, CLASS_IN, 3600); 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 { a->
RCODE =
RCODE_SRVFAIL; }
return a; }
00001 00002
#define POS_DEFAULTLOG 00003
#define POS_DEFAULTLOG_STDERR 00004
#define POS_DEFAULTLOG_SYSLOG 00005
00006 00007
#include <poslib/server/server.h> 00008 00009 00010 00011
#include 00012
#include 00013 00014
DnsMessage *my_handle_query(
pending_query *query); 00015 00016
void cleanup(
int sig) { 00017 00018
pos_setquitflag(); 00019 } 00020 00021
int main(
int argc,
char **argv) { 00022
_addr a; 00023 00024
try { 00025 00026
if (argc == 2 && argv[1][0] ==
'@') { 00027
txt_to_addr(&a, argv[1] + 1); 00028 }
else { 00029
txt_to_addr(&a,
"any"); 00030 00031 00032 } 00033 00034 00035 servers.push_front(
ServerSocket(ss_udp,
udpcreateserver(&a))); 00036 servers.push_front(
ServerSocket(ss_tcp,
tcpcreateserver(&a))); 00037 00038 00039
pos_log(context_none, log_info,
"Posadis example server starting up..."); 00040 00041 00042 signal(SIGINT, cleanup); 00043 signal(SIGTERM, cleanup); 00044 00045 00046 00047
handle_query = my_handle_query; 00048 00049 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 00060
DnsMessage *my_handle_query(
pending_query *query) { 00061
DnsMessage *a =
new DnsMessage(); 00062
DnsQuestion q; 00063
DnsRR rr; 00064 00065 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 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 00083 rr =
DnsRR(q.
QNAME, DNS_TYPE_A, CLASS_IN, 3600); 00084 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 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
1.3.7