pdb_server.c

00001 /*
00002  * Copyright (C) 2009 1&1 Internet AG
00003  *
00004  * This file is part of sip-router, a free SIP server.
00005  *
00006  * sip-router is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version
00010  *
00011  * sip-router is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License 
00017  * along with this program; if not, write to the Free Software 
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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  Receive query request and send answer via UDP.
00073  UDP Payload of request must contain the phone number (only digits allowed).
00074  The Answer contains the number of the request followed by '\0' and the carrier id.
00075  Loops until a receive or send error occurs and returns -1.
00076  However, the following errors are ignored: EAGAIN, EINTR, EWOULDBLOCK.
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)]; /* additional space for '\0' termination and carrier */
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                 /* take only digits */
00100                 i=0;
00101                 while ((i<bytes_received) && (buf[i]>='0') && (buf[i]<='9')) i++;
00102                 buf[i]=0; /* terminate string */
00103                 i++;
00104 
00105                 carrierid=lookup_number(buf);
00106                 
00107                 /* convert to network byte order*/
00108                 carrierid=htons(carrierid);
00109 
00110                 /* append carrier id to answer */
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 }