root/trunk/pdns/pdns/dynlistener.cc @ 2

Revision 2, 5.2 KB (checked in by ahu, 10 years ago)

Initial revision

  • Property svn:eol-style set to native
  • Property svn:keywords set to author date id revision
Line 
1/*
2    PowerDNS Versatile Database Driven Nameserver
3    Copyright (C) 2002  PowerDNS.COM BV
4
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18*/
19// $Id: dynlistener.cc,v 1.1 2002/11/27 15:18:33 ahu Exp $
20/* (C) Copyright 2002 PowerDNS.COM BV */
21#include <cstring>
22#include <string>
23#include <map>
24#include <sys/types.h>
25#include <sys/un.h>
26#include <dlfcn.h>
27#include <pthread.h>
28#include <unistd.h>
29
30#include <sys/socket.h>
31#include <netinet/in.h>
32#include <errno.h>
33#include <iostream>
34#include <sstream>
35#include <sys/types.h>
36#include <signal.h>
37
38#include <sys/stat.h>
39#include <fcntl.h>
40#include <unistd.h>
41
42#include "misc.hh"
43#include "dns.hh"
44#include "arguments.hh"
45#include "dnsbackend.hh"
46#include "dynlistener.hh"
47#include "dnspacket.hh"
48#include "logger.hh"
49#include "statbag.hh"
50
51
52
53extern StatBag S;
54
55DynListener::DynListener(const string &pname)
56{
57  d_restfunc=0;
58  string programname=pname;
59
60  if(!programname.empty()) {
61    struct sockaddr_un local;
62    d_s=socket(AF_UNIX,SOCK_DGRAM,0);
63
64    if(d_s<0) {
65      L<<Logger::Error<<"creating socket for dynlistener: "<<strerror(errno)<<endl;;
66      exit(1);
67    }
68
69    int tmp=1;
70    if(setsockopt(d_s,SOL_SOCKET,SO_REUSEADDR,(char*)&tmp,sizeof tmp)<0)
71      throw AhuException(string("Setsockopt failed: ")+strerror(errno));
72   
73    string socketname=arg()["socket-dir"]+"/";
74    cleanSlashes(socketname);
75   
76    if(!mkdir(socketname.c_str(),0700)) // make /var directory, if needed
77      L<<Logger::Warning<<"Created local state directory '"<<socketname<<"'"<<endl;
78    else if(errno!=EEXIST) {
79      L<<Logger::Critical<<"FATAL: Unable to create socket directory ("<<socketname<<") and it does not exist yet"<<endl;
80      exit(1);
81    }
82   
83    socketname+=programname+".controlsocket";
84    unlink(socketname.c_str());
85    memset(&local,0,sizeof(local));
86    local.sun_family=AF_UNIX;
87    strcpy(local.sun_path,socketname.c_str());
88   
89    if(bind(d_s, (sockaddr*)&local,sizeof(local))<0) {
90      L<<Logger::Critical<<"binding to dynlistener '"<<socketname<<"': "<<strerror(errno)<<endl;
91      exit(1);
92    }
93 
94    if(!arg()["setgid"].empty()) {
95      if(chown(socketname.c_str(),static_cast<uid_t>(-1),Utility::makeGidNumeric(arg()["setgid"]))<0)
96        L<<Logger::Error<<"Unable to change group ownership of controlsocket: "<<strerror(errno)<<endl;
97      if(chmod(socketname.c_str(),0660)<0)
98        L<<Logger::Error<<"Unable to change group access mode of controlsocket: "<<strerror(errno)<<endl;
99    }
100     
101
102    L<<Logger::Warning<<"Listening on controlsocket in '"<<socketname<<"'"<<endl;
103    d_udp=true;
104  }
105  else
106    d_udp=false;
107 
108
109}
110
111void DynListener::go()
112{
113  d_ppid=getpid();
114  pthread_create(&d_tid,0,&DynListener::theListenerHelper,this);
115}
116
117void *DynListener::theListenerHelper(void *p)
118{
119  DynListener *us=static_cast<DynListener *>(p);
120  us->theListener();
121  return 0;
122}
123
124string DynListener::getLine()
125{
126  char mesg[512];
127  memset(mesg,0,sizeof(mesg));
128  int len;
129   
130  if(d_udp) {
131    d_addrlen=sizeof(d_remote);
132
133    if((len=recvfrom(d_s,mesg,512,0,(sockaddr*) &d_remote, &d_addrlen))<0) {
134      L<<Logger::Error<<"Unable to receive packet from controlsocket ("<<d_s<<") - exiting: "<<strerror(errno)<<endl;
135      exit(1);
136    }
137  }
138  else {
139    if(isatty(0))
140      write(1, "% ", 2);
141    if((len=read(0,mesg,512))<0) 
142      throw AhuException("Reading from the control pipe: "+stringerror());
143    else if(len==0)
144      throw AhuException("Guardian exited - going down as well");
145  }
146 
147  return mesg;
148}
149
150void DynListener::sendLine(const string &l)
151{
152  if(d_udp)
153    sendto(d_s,l.c_str(),l.length()+1,0,(struct sockaddr *)&d_remote,d_addrlen);       
154  else {
155    string line=l;
156    line.append("\n");
157    write(1,line.c_str(),line.length());
158  }
159}
160
161void DynListener::registerFunc(const string &name, g_funk_t *gf)
162{
163  d_funcdb[name]=gf;
164}
165
166void DynListener::registerRestFunc(g_funk_t *gf)
167{
168  d_restfunc=gf;
169}
170
171void DynListener::theListener()
172{
173  try {
174    map<string,string> parameters;
175
176    for(;;) {
177      string line=getLine();
178      chomp(line,"\n");
179
180      vector<string>parts;
181      stringtok(parts,line," ");
182      if(parts.empty()) {
183        sendLine("Empty line");
184        continue;
185      }
186      upperCase(parts[0]);
187      if(!d_funcdb[parts[0]]) {
188        if(d_restfunc) 
189          sendLine((*d_restfunc)(parts,d_ppid));
190        else
191          sendLine("Unknown command: '"+parts[0]+"'");
192        continue;
193      }
194
195      sendLine((*d_funcdb[parts[0]])(parts,d_ppid));
196    }
197  }
198  catch(AhuException &AE)
199    {
200      L<<Logger::Error<<"Fatal: "<<AE.reason<<endl;
201    }
202  catch(string &E)
203    {
204      L<<Logger::Error<<"Fatal: "<<E<<endl;
205    }
206  catch(...)
207    {
208      L<<Logger::Error<<"Fatal: unknown exception occured"<<endl;
209    }
210}
211
Note: See TracBrowser for help on using the browser.