PageRenderTime 49ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/utils/pdbt/pdb_server.c

https://gitlab.com/oded/kamailio
C | 295 lines | 211 code | 43 blank | 41 comment | 33 complexity | 823d51ca1a2c3cf7745b909bf12e1059 MD5 | raw file
  1. /*
  2. * Copyright (C) 2009 1&1 Internet AG
  3. *
  4. * This file is part of sip-router, a free SIP server.
  5. *
  6. * sip-router is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version
  10. *
  11. * sip-router is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19. */
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <unistd.h>
  23. #include <string.h>
  24. #include <errno.h>
  25. #include <sys/socket.h>
  26. #include <netinet/in.h>
  27. #include <arpa/inet.h>
  28. #include "pdb_server_backend.h"
  29. #include "log.h"
  30. #define NETBUFSIZE 200
  31. #define DEFAULT_BINDADDR "0.0.0.0"
  32. #define DEFAULT_PORT 5574
  33. void print_usage(char *program) {
  34. set_log_level(LOG_INFO);
  35. LINFO("Listens on a UDP port for queries and sends answer UDP\n");
  36. LINFO("packets back.\n");
  37. LINFO("\n");
  38. LINFO("Usage: %s [<option>...]\n", program);
  39. LINFO(" %s -m <data file> [-i <bind addr>] [-p <port>] [-d <log level>]\n", program);
  40. LINFO("\n");
  41. LINFO(" Options:\n");
  42. LINFO(" -m <file>: Specifies the file containing the backend data.\n");
  43. LINFO(" -i <bind addr>: Specifies the address to bind the UDP socket to.\n");
  44. LINFO(" Default is '%s'.\n", DEFAULT_BINDADDR);
  45. LINFO(" -p <port>: Specifies the port to listen at in udp_server mode.\n");
  46. LINFO(" Default is %ld.\n", (long int)DEFAULT_PORT);
  47. LINFO(" -d <debug level>: %ld for debug level.\n", LOG_DEBUG);
  48. LINFO(" %ld for info level.\n", LOG_INFO);
  49. LINFO(" %ld for notice level.\n", LOG_NOTICE);
  50. LINFO(" %ld for warning level.\n", LOG_WARNING);
  51. LINFO(" %ld for error level.\n", LOG_ERR);
  52. LINFO(" %ld for critical level.\n", LOG_CRIT);
  53. LINFO(" %ld for alert level.\n", LOG_ALERT);
  54. LINFO(" %ld for emergency level.\n", LOG_EMERG);
  55. LINFO(" %ld to disable all messages.\n", LOG_EMERG-1);
  56. LINFO(" Default is warning level.\n");
  57. LINFO(" -h: Print this help.\n");
  58. }
  59. int pdb_msg_server_send(int so, char *buf, size_t answerlen, struct sockaddr *fromaddr, socklen_t fromaddrlen)
  60. {
  61. ssize_t bytes_sent;
  62. int try = 0;
  63. again:
  64. bytes_sent = sendto(so, buf, answerlen, 0, fromaddr, fromaddrlen);
  65. if (bytes_sent < 3) {
  66. if ((errno == EINTR) && (try < 3)) {
  67. try++;
  68. LERR("sendto() failed - trying again. errno=%d (%s)\n", errno, strerror(errno));
  69. goto again;
  70. }
  71. LERR("sendto() failed with errno=%d (%s)\n", errno, strerror(errno));
  72. if ((errno==EAGAIN)||(errno==EINTR)||(errno==EWOULDBLOCK)) return 0;
  73. return -1;
  74. }
  75. if (bytes_sent != answerlen) {
  76. LERR("cannot send the whole answer (%ld/%ld).\n", (long int)bytes_sent, (long int)answerlen);
  77. return 0;
  78. }
  79. return 0;
  80. }
  81. /*
  82. Receive query request and send answer via UDP.
  83. UDP Payload of request must contain the phone number (only digits allowed).
  84. The Answer contains the number of the request followed by '\0' and the carrier id.
  85. Loops until a receive or send error occurs and returns -1.
  86. However, the following errors are ignored: EAGAIN, EINTR, EWOULDBLOCK.
  87. */
  88. int udp_server(int so)
  89. {
  90. struct pdb_msg msg;
  91. struct sockaddr fromaddr;
  92. socklen_t fromaddrlen;
  93. size_t answerlen = 0;
  94. ssize_t bytes_received;
  95. carrier_t carrierid;
  96. char buf[sizeof(struct pdb_msg)];
  97. int i;
  98. for (;;) {
  99. fromaddrlen = sizeof(fromaddr);
  100. bytes_received = recvfrom(so, buf, sizeof(struct pdb_msg), 0, &fromaddr, &fromaddrlen);
  101. if (bytes_received<0) {
  102. LERR("recvfrom() failed with errno=%d (%s)\n", errno, strerror(errno));
  103. if ((errno==EAGAIN)||(errno==EINTR)||(errno==EWOULDBLOCK)) continue;
  104. return -1;
  105. }
  106. switch (buf[0]) {
  107. case PDB_VERSION_1:
  108. /* get received bytes */
  109. memcpy(&msg, buf, bytes_received);
  110. // pdb_msg_dbg(msg);
  111. short int *_id = (short int *)&(msg.hdr.id); /* make gcc happy */
  112. msg.hdr.id = ntohs(*_id);
  113. i = 0;
  114. while (i < strlen(msg.bdy.payload)) {
  115. if (msg.bdy.payload[i] < '0' || msg.bdy.payload[i] > '9') {
  116. pdb_msg_format_send(&msg, PDB_VERSION_1, PDB_TYPE_REPLY_ID, PDB_CODE_NOT_NUMBER, htons(msg.hdr.id), NULL, 0);
  117. goto msg_send;
  118. }
  119. i++;
  120. }
  121. /* lookup pdb_id */
  122. carrierid=lookup_number(msg.bdy.payload);
  123. /* check if not found pdb_id */
  124. if (carrierid == 0) {
  125. pdb_msg_format_send(&msg, PDB_VERSION_1, PDB_TYPE_REPLY_ID, PDB_CODE_NOT_FOUND, htons(msg.hdr.id), NULL, 0);
  126. goto msg_send;
  127. }
  128. /* convert to network byte order*/
  129. carrierid = htons(carrierid);
  130. /* prepare the message payload to be sent
  131. * add the number string and append the carrier id
  132. */
  133. memcpy(buf, msg.bdy.payload, msg.hdr.length - sizeof(msg.hdr));
  134. memcpy(buf + msg.hdr.length - sizeof(msg.hdr), &carrierid, sizeof(carrierid));
  135. /* all ok, send pdb_msg with pdb_id in payload */
  136. pdb_msg_format_send(&msg, PDB_VERSION_1, PDB_TYPE_REPLY_ID, PDB_CODE_OK, htons(msg.hdr.id), buf, msg.hdr.length - sizeof(msg.hdr) + sizeof(carrierid));
  137. goto msg_send;
  138. break;
  139. /* old pdb version; no pdb_msg used */
  140. default:
  141. /* take only digits */
  142. i=0;
  143. while ((i<bytes_received) && (buf[i]>='0') && (buf[i]<='9')) i++;
  144. buf[i]=0; /* terminate string */
  145. i++;
  146. /* lookup pdb_id */
  147. carrierid=lookup_number(buf);
  148. /* convert to network byte order*/
  149. carrierid=htons(carrierid);
  150. /* append carrier id to answer */
  151. memcpy(&(buf[i]), &carrierid, sizeof(carrierid));
  152. answerlen=i+sizeof(carrierid);
  153. goto buf_send;
  154. break;
  155. }
  156. msg_send:
  157. // pdb_msg_dbg(msg);
  158. if (pdb_msg_server_send(so, (char*)&msg, msg.hdr.length, &fromaddr, fromaddrlen) < 0) {
  159. return -1;
  160. }
  161. continue;
  162. buf_send:
  163. if (pdb_msg_server_send(so, buf, answerlen, &fromaddr, fromaddrlen)) {
  164. return -1;
  165. }
  166. continue;
  167. }
  168. return -1;
  169. }
  170. int main(int argc, char *argv[]) {
  171. int opt;
  172. char *backend_data_filename = NULL;
  173. char *bind_addr = DEFAULT_BINDADDR;
  174. unsigned short bind_port = DEFAULT_PORT;
  175. int use_syslog = 0;
  176. int log_level=LOG_WARNING;
  177. long int ret;
  178. int so;
  179. struct sockaddr_in sa;
  180. while ((opt = getopt(argc, argv, "m:i:p:hdl:")) != -1) {
  181. switch (opt) {
  182. case 'm':
  183. backend_data_filename = optarg;
  184. break;
  185. case 'i':
  186. bind_addr=optarg;
  187. break;
  188. case 'p':
  189. ret=strtol(optarg, NULL, 10);
  190. if ((ret<0) || (ret>65535)) {
  191. init_log("pdb_server", use_syslog);
  192. LERR("invalid port '%s' specified.\n", optarg);
  193. return -1;
  194. }
  195. bind_port=ret;
  196. break;
  197. case 'h':
  198. init_log("pdb_server", use_syslog);
  199. print_usage(argv[0]);
  200. return 0;
  201. break;
  202. case 'd':
  203. use_syslog=1;
  204. break;
  205. case 'l':
  206. ret=strtol(optarg, NULL, 10);
  207. if ((ret<LOG_EMERG-1) || (ret>LOG_DEBUG)) {
  208. init_log("pdb_server", use_syslog);
  209. LERR("invalid log level '%s' specified.\n", optarg);
  210. return -1;
  211. }
  212. log_level=ret;
  213. break;
  214. default:
  215. init_log("pdb_server", use_syslog);
  216. LERR("invalid option '%c'.\n", opt);
  217. print_usage(argv[0]);
  218. return 1;
  219. }
  220. }
  221. init_log("pdb_server", use_syslog);
  222. set_log_level(log_level);
  223. if (backend_data_filename==NULL) {
  224. LERR("no data file specified.\n");
  225. return 1;
  226. }
  227. if (init_backend(backend_data_filename)<0) {
  228. LERR("cannot initialize backend.\n");
  229. return -1;
  230. }
  231. so = socket(AF_INET, SOCK_DGRAM, 0);
  232. if (so<0) {
  233. LERR("socket() failed with errno=%d (%s)\n", errno, strerror(errno));
  234. return -1;
  235. }
  236. memset(&sa, 0, sizeof(sa));
  237. sa.sin_family = AF_INET;
  238. sa.sin_port = htons(bind_port);
  239. if (inet_aton(bind_addr, &(sa.sin_addr))==0) {
  240. LERR("invalid address '%s'.\n", bind_addr);
  241. close(so);
  242. return -1;
  243. }
  244. if (bind(so, (struct sockaddr *) &sa, sizeof(sa))<0) {
  245. LERR("bind() failed with errno=%d (%s)\n", errno, strerror(errno));
  246. close(so);
  247. return -1;
  248. }
  249. udp_server(so);
  250. close(so);
  251. return 0;
  252. }