ctrl_socks.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. /*
  2. * $Id$
  3. *
  4. * Copyright (C) 2006 iptelorg GmbH
  5. *
  6. * This file is part of ser, a free SIP server.
  7. *
  8. * ser is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version
  12. *
  13. * For a license to use the ser software under conditions
  14. * other than those described here, or to purchase support for this
  15. * software, please contact iptel.org by e-mail at the following addresses:
  16. * [email protected]
  17. *
  18. * ser is distributed in the hope that it will be useful,
  19. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. * GNU General Public License for more details.
  22. *
  23. * You should have received a copy of the GNU General Public License
  24. * along with this program; if not, write to the Free Software
  25. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  26. */
  27. /* History:
  28. * --------
  29. * 2006-02-14 created by andrei
  30. */
  31. #include "ctrl_socks.h"
  32. #include "init_socks.h"
  33. #include "../../dprint.h"
  34. #include "../../mem/mem.h"
  35. #include "../../ut.h"
  36. #ifdef USE_FIFO
  37. #include "fifo_server.h"
  38. #endif
  39. #include "ctl.h"
  40. /* parse proto:address:port or proto:address */
  41. /* returns struct id_list on success (ctl_malloc'ed), 0 on error
  42. * WARNING: it will add \0 in the string*/
  43. /* parses:
  44. * tcp|udp|unix:host_name:port
  45. * tcp|udp|unix:host_name
  46. * host_name:port
  47. * host_name
  48. *
  49. *
  50. * where host_name=string, ipv4 address, [ipv6 address],
  51. * unix socket path (starts with '/')
  52. */
  53. struct id_list* parse_listen_id(char* l, int len, enum socket_protos def)
  54. {
  55. char* p;
  56. enum socket_protos proto;
  57. char* name;
  58. char* port_str;
  59. int port;
  60. int err;
  61. struct servent* se;
  62. char* s;
  63. struct id_list* id;
  64. s=ctl_malloc((len+1)*sizeof(char));
  65. if (s==0){
  66. LOG(L_ERR, "ERROR:parse_listen_id: out of memory\n");
  67. goto error;
  68. }
  69. memcpy(s, l, len);
  70. s[len]=0; /* null terminate */
  71. /* duplicate */
  72. proto=UNKNOWN_SOCK;
  73. port=0;
  74. name=0;
  75. port_str=0;
  76. p=s;
  77. if ((*p)=='[') goto ipv6;
  78. /* find proto or name */
  79. for (; *p; p++){
  80. if (*p==':'){
  81. *p=0;
  82. if (strcasecmp("tcp", s)==0){
  83. proto=TCP_SOCK;
  84. goto find_host;
  85. }else if (strcasecmp("udp", s)==0){
  86. proto=UDP_SOCK;
  87. goto find_host;
  88. }else if (strcasecmp("unixd", s)==0){
  89. proto=UNIXD_SOCK;
  90. goto find_host;
  91. }else if ((strcasecmp("unix", s)==0)||(strcasecmp("unixs", s)==0)){
  92. proto=UNIXS_SOCK;
  93. goto find_host;
  94. #ifdef USE_FIFO
  95. }else if (strcasecmp("fifo", s)==0){
  96. proto=FIFO_SOCK;
  97. goto find_host;
  98. #endif
  99. }else{
  100. proto=UNKNOWN_SOCK;
  101. /* this might be the host */
  102. name=s;
  103. goto find_port;
  104. }
  105. }
  106. }
  107. name=s;
  108. goto end; /* only name found */
  109. find_host:
  110. p++;
  111. if (*p=='[') goto ipv6;
  112. name=p;
  113. for (; *p; p++){
  114. if ((*p)==':'){
  115. *p=0;
  116. goto find_port;
  117. }
  118. }
  119. goto end; /* nothing after name */
  120. ipv6:
  121. name=p;
  122. p++;
  123. for(;*p;p++){
  124. if(*p==']'){
  125. if(*(p+1)==':'){
  126. p++; *p=0;
  127. goto find_port;
  128. }else if (*(p+1)==0) goto end;
  129. }else{
  130. goto error;
  131. }
  132. }
  133. find_port:
  134. p++;
  135. port_str=(*p)?p:0;
  136. end:
  137. /* fix all the stuff */
  138. if (name==0) goto error;
  139. if (proto==UNKNOWN_SOCK){
  140. /* try to guess */
  141. if (port_str){
  142. switch(def){
  143. case TCP_SOCK:
  144. case UDP_SOCK:
  145. proto=def;
  146. break;
  147. default:
  148. proto=UDP_SOCK;
  149. DBG("guess:%s is a tcp socket\n", name);
  150. }
  151. }else if (name && strchr(name, '/')){
  152. switch(def){
  153. case TCP_SOCK:
  154. case UDP_SOCK:
  155. DBG("guess:%s is a unix socket\n", name);
  156. proto=UNIXS_SOCK;
  157. break;
  158. default:
  159. /* def is filename based => use default */
  160. proto=def;
  161. }
  162. }else{
  163. /* using default */
  164. proto=def;
  165. }
  166. }
  167. if (port_str){
  168. port=str2s(port_str, strlen(port_str), &err);
  169. if (err){
  170. /* try getservbyname */
  171. se=getservbyname(port_str,
  172. (proto==TCP_SOCK)?"tcp":(proto==UDP_SOCK)?"udp":0);
  173. if (se) port=ntohs(se->s_port);
  174. else goto error;
  175. }
  176. }else{
  177. /* no port, check if the hostname is a port
  178. * (e.g. tcp:3012 == tcp:*:3012 */
  179. if (proto==TCP_SOCK|| proto==UDP_SOCK){
  180. port=str2s(name, strlen(name), &err);
  181. if (err){
  182. port=0;
  183. }else{
  184. name="*"; /* inaddr any */
  185. }
  186. }
  187. }
  188. id=ctl_malloc(sizeof(struct id_list));
  189. if (id==0){
  190. LOG(L_ERR, "ERROR:parse_listen_id: out of memory\n");
  191. goto error;
  192. }
  193. id->name=name;
  194. id->proto=proto;
  195. id->data_proto=P_BINRPC;
  196. id->port=port;
  197. id->buf=s;
  198. id->next=0;
  199. return id;
  200. error:
  201. if (s) ctl_free(s);
  202. return 0;
  203. }
  204. void free_id_list_elem(struct id_list* id)
  205. {
  206. if (id->buf){
  207. ctl_free(id->buf);
  208. id->buf=0;
  209. }
  210. }
  211. void free_id_list(struct id_list* l)
  212. {
  213. struct id_list* nxt;
  214. for (;l; l=nxt){
  215. nxt=l->next;
  216. free_id_list_elem(l);
  217. ctl_free(l);
  218. }
  219. }
  220. int init_ctrl_sockets(struct ctrl_socket** c_lst, struct id_list* lst,
  221. int def_port, int perm, int uid, int gid)
  222. {
  223. struct id_list* l;
  224. int s;
  225. struct ctrl_socket* cs;
  226. int extra_fd;
  227. union sockaddr_u su;
  228. for (l=lst; l; l=l->next){
  229. extra_fd=-1;
  230. switch(l->proto){
  231. case UNIXS_SOCK:
  232. s=init_unix_sock(&su.sa_un, l->name, SOCK_STREAM,
  233. perm, uid, gid);
  234. break;
  235. case UNIXD_SOCK:
  236. s=init_unix_sock(&su.sa_un, l->name, SOCK_DGRAM,
  237. perm, uid, gid);
  238. break;
  239. case TCP_SOCK:
  240. if (l->port==0) l->port=def_port;
  241. s=init_tcpudp_sock(&su.sa_in, l->name, l->port, TCP_SOCK);
  242. break;
  243. case UDP_SOCK:
  244. if (l->port==0) l->port=def_port;
  245. s=init_tcpudp_sock(&su.sa_in, l->name, l->port, UDP_SOCK);
  246. break;
  247. #ifdef USE_FIFO
  248. case FIFO_SOCK:
  249. s=init_fifo_fd(l->name, perm, uid, gid, &extra_fd);
  250. break;
  251. #endif
  252. default:
  253. LOG(L_ERR, "ERROR: init_ctrl_listeners: unsupported"
  254. " proto %d\n", l->proto);
  255. continue;
  256. }
  257. if (s==-1) goto error;
  258. /* add listener */
  259. cs=ctl_malloc(sizeof(struct ctrl_socket));
  260. if (cs==0){
  261. LOG(L_ERR, "ERROR: init_ctrl_listeners: out of memory\n");
  262. goto error;
  263. }
  264. memset(cs,0, sizeof(struct ctrl_socket));
  265. cs->transport=l->proto;
  266. cs->p_proto=l->data_proto;
  267. cs->fd=s;
  268. cs->write_fd=extra_fd; /* needed for fifo write */
  269. cs->name=l->name;
  270. cs->port=l->port;
  271. cs->u=su;
  272. /* add it to the list */
  273. cs->next=*c_lst;
  274. *c_lst=cs;
  275. }
  276. return 0;
  277. error:
  278. return -1;
  279. }
  280. void free_ctrl_socket_list(struct ctrl_socket* l)
  281. {
  282. struct ctrl_socket* nxt;
  283. for (;l; l=nxt){
  284. nxt=l->next;
  285. if (l->data)
  286. ctl_free(l->data);
  287. ctl_free(l);
  288. }
  289. }