00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 #include <unistd.h>
00024 #include <string.h>
00025 #include <errno.h>
00026 #include <sys/socket.h>
00027 #include <netinet/in.h>
00028 #include <arpa/inet.h>
00029 #include "pdb_server_backend.h"
00030 #include "log.h"
00031
00032
00033
00034 #define NETBUFSIZE 200
00035 #define DEFAULT_BINDADDR "0.0.0.0"
00036 #define DEFAULT_PORT 5574
00037
00038
00039
00040
00041 void print_usage(char *program) {
00042 set_log_level(LOG_INFO);
00043 LINFO("Listens on a UDP port for queries and sends answer UDP\n");
00044 LINFO("packets back.\n");
00045 LINFO("\n");
00046 LINFO("Usage: %s [<option>...]\n", program);
00047 LINFO(" %s -m <data file> [-i <bind addr>] [-p <port>] [-d <log level>]\n", program);
00048 LINFO("\n");
00049 LINFO(" Options:\n");
00050 LINFO(" -m <file>: Specifies the file containing the backend data.\n");
00051 LINFO(" -i <bind addr>: Specifies the address to bind the UDP socket to.\n");
00052 LINFO(" Default is '%s'.\n", DEFAULT_BINDADDR);
00053 LINFO(" -p <port>: Specifies the port to listen at in udp_server mode.\n");
00054 LINFO(" Default is %ld.\n", (long int)DEFAULT_PORT);
00055 LINFO(" -d <debug level>: %ld for debug level.\n", LOG_DEBUG);
00056 LINFO(" %ld for info level.\n", LOG_INFO);
00057 LINFO(" %ld for notice level.\n", LOG_NOTICE);
00058 LINFO(" %ld for warning level.\n", LOG_WARNING);
00059 LINFO(" %ld for error level.\n", LOG_ERR);
00060 LINFO(" %ld for critical level.\n", LOG_CRIT);
00061 LINFO(" %ld for alert level.\n", LOG_ALERT);
00062 LINFO(" %ld for emergency level.\n", LOG_EMERG);
00063 LINFO(" %ld to disable all messages.\n", LOG_EMERG-1);
00064 LINFO(" Default is warning level.\n");
00065 LINFO(" -h: Print this help.\n");
00066 }
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078 int udp_server(int so)
00079 {
00080 struct sockaddr fromaddr;
00081 socklen_t fromaddrlen;
00082 size_t answerlen;
00083 ssize_t bytes_received;
00084 ssize_t bytes_sent;
00085 carrier_t carrierid;
00086 char buf[NETBUFSIZE+1+sizeof(carrierid)];
00087 int i;
00088 int try;
00089
00090 for (;;) {
00091 fromaddrlen = sizeof(fromaddr);
00092 bytes_received = recvfrom(so, buf, NETBUFSIZE, 0, &fromaddr, &fromaddrlen);
00093 if (bytes_received<0) {
00094 LERR("recvfrom() failed with errno=%d (%s)\n", errno, strerror(errno));
00095 if ((errno==EAGAIN)||(errno==EINTR)||(errno==EWOULDBLOCK)) continue;
00096 return -1;
00097 }
00098
00099
00100 i=0;
00101 while ((i<bytes_received) && (buf[i]>='0') && (buf[i]<='9')) i++;
00102 buf[i]=0;
00103 i++;
00104
00105 carrierid=lookup_number(buf);
00106
00107
00108 carrierid=htons(carrierid);
00109
00110
00111 memcpy(&(buf[i]), &carrierid, sizeof(carrierid));
00112 answerlen=i+sizeof(carrierid);
00113
00114 try=0;
00115 again:
00116 bytes_sent = sendto(so, buf, answerlen, 0, &fromaddr, fromaddrlen);
00117 if (bytes_sent < 3) {
00118 if ((errno==EINTR) && (try<3)) {
00119 try++;
00120 LERR("sendto() failed - trying again. errno=%d (%s)\n", errno, strerror(errno));
00121 goto again;
00122 }
00123 LERR("sendto() failed with errno=%d (%s)\n", errno, strerror(errno));
00124 if ((errno==EAGAIN)||(errno==EINTR)||(errno==EWOULDBLOCK)) continue;
00125 return -1;
00126 }
00127 if (bytes_sent != answerlen) {
00128 LERR("cannot send the whole answer (%ld/%ld).\n", (long int)bytes_sent, (long int)answerlen);
00129 continue;
00130 }
00131 }
00132
00133 return 0;
00134 }
00135
00136
00137
00138
00139 int main(int argc, char *argv[]) {
00140 int opt;
00141 char *backend_data_filename = NULL;
00142 char *bind_addr = DEFAULT_BINDADDR;
00143 unsigned short bind_port = DEFAULT_PORT;
00144 int use_syslog = 0;
00145 int log_level=LOG_WARNING;
00146
00147 long int ret;
00148
00149 int so;
00150 struct sockaddr_in sa;
00151
00152 while ((opt = getopt(argc, argv, "m:i:p:hdl:")) != -1) {
00153 switch (opt) {
00154 case 'm':
00155 backend_data_filename = optarg;
00156 break;
00157 case 'i':
00158 bind_addr=optarg;
00159 break;
00160 case 'p':
00161 ret=strtol(optarg, NULL, 10);
00162 if ((ret<0) || (ret>65535)) {
00163 init_log("pdb_server", use_syslog);
00164 LERR("invalid port '%s' specified.\n", optarg);
00165 return -1;
00166 }
00167 bind_port=ret;
00168 break;
00169 case 'h':
00170 init_log("pdb_server", use_syslog);
00171 print_usage(argv[0]);
00172 return 0;
00173 break;
00174 case 'd':
00175 use_syslog=1;
00176 break;
00177 case 'l':
00178 ret=strtol(optarg, NULL, 10);
00179 if ((ret<LOG_EMERG-1) || (ret>LOG_DEBUG)) {
00180 init_log("pdb_server", use_syslog);
00181 LERR("invalid log level '%s' specified.\n", optarg);
00182 return -1;
00183 }
00184 log_level=ret;
00185 break;
00186 default:
00187 init_log("pdb_server", use_syslog);
00188 LERR("invalid option '%c'.\n", opt);
00189 print_usage(argv[0]);
00190 return 1;
00191 }
00192 }
00193
00194 init_log("pdb_server", use_syslog);
00195 set_log_level(log_level);
00196
00197 if (backend_data_filename==NULL) {
00198 LERR("no data file specified.\n");
00199 return 1;
00200 }
00201
00202 if (init_backend(backend_data_filename)<0) {
00203 LERR("cannot initialize backend.\n");
00204 return -1;
00205 }
00206
00207 so = socket(AF_INET, SOCK_DGRAM, 0);
00208 if (so<0) {
00209 LERR("socket() failed with errno=%d (%s)\n", errno, strerror(errno));
00210 return -1;
00211 }
00212
00213 memset(&sa, 0, sizeof(sa));
00214 sa.sin_family = AF_INET;
00215 sa.sin_port = htons(bind_port);
00216 if (inet_aton(bind_addr, &(sa.sin_addr))==0) {
00217 LERR("invalid address '%s'.\n", bind_addr);
00218 close(so);
00219 return -1;
00220 }
00221
00222 if (bind(so, (struct sockaddr *) &sa, sizeof(sa))<0) {
00223 LERR("bind() failed with errno=%d (%s)\n", errno, strerror(errno));
00224 close(so);
00225 return -1;
00226 }
00227
00228 udp_server(so);
00229 close(so);
00230
00231 return 0;
00232 }