repslave.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. #ident "@(#)repslave.c 1.15 99/06/09"
  2. /** BEGIN COPYRIGHT BLOCK
  3. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  4. * Copyright (C) 2006 Red Hat, Inc.
  5. * All rights reserved.
  6. *
  7. * License: GPL (version 3 or any later version).
  8. * See LICENSE for details.
  9. * END COPYRIGHT BLOCK **/
  10. #ifdef HAVE_CONFIG_H
  11. # include <config.h>
  12. #endif
  13. /*
  14. FILE : repslave.c
  15. AUTHOR : Fabio Pistolesi
  16. VERSION : 1.0
  17. DATE : 05 May 1999
  18. DESCRIPTION :
  19. This file contains the implementation of the slave part
  20. of ldclt tool. This slave is intended to scan the logs
  21. of the ldap server and to communicate the operations
  22. logged to the master ldclt, to be checked against the
  23. memorized operations performed on the master ldap
  24. server.
  25. LOCAL : None.
  26. HISTORY :
  27. ---------+--------------+------------------------------------------------------
  28. dd/mm/yy | Author | Comments
  29. ---------+--------------+------------------------------------------------------
  30. 05/05/99 | F. Pistolesi | Creation
  31. ---------+--------------+------------------------------------------------------
  32. 06/05/99 | JL Schwing | 1.2 : Port on Solaris 2.5.1
  33. ---------+--------------+------------------------------------------------------
  34. 10/05/99 | F. Pistolesi | Added multiple filtered servers to send results to.
  35. ---------+--------------+------------------------------------------------------
  36. 18/05/99 | JL Schwing | 1.8 : Port on 2.5.1
  37. ---------+--------------+------------------------------------------------------
  38. 26/05/99 | F. Pistolesi | 1.10: Bug fix - missing free()
  39. ---------+--------------+------------------------------------------------------
  40. 27/05/99 | F. Pistolesi | 1.11: Add new option -d (debug)
  41. ---------+--------------+------------------------------------------------------
  42. 29/05/99 | F. Pistolesi | 1.12: Add new option -t (log)
  43. ---------+--------------+------------------------------------------------------
  44. 09/06/99 | JL Schwing | 1.14: Bug fix - crash in send_op() if tmp.dn==NULL
  45. ---------+--------------+------------------------------------------------------
  46. 09/06/99 | F. Pistolesi | 1.15: Fix the fix above.
  47. ---------+--------------+------------------------------------------------------
  48. */
  49. #include <stdio.h>
  50. #include <time.h>
  51. #include <string.h>
  52. #include <signal.h>
  53. #include <libgen.h>
  54. #if OS_RELEASE == 551
  55. #include <re_comp.h>
  56. #endif
  57. #include "remote.h"
  58. #include "lber.h"
  59. #include "ldap.h"
  60. /*
  61. * Enumeration for internal list
  62. */
  63. enum {ADD,DELETE,MODRDN,MODIFY,RESULT,LAST};
  64. /*
  65. * internal list
  66. */
  67. typedef struct {
  68. int conn,op,type;
  69. char *dn;
  70. } Optype;
  71. typedef struct {
  72. int fd;
  73. char *filter,*hname;
  74. struct sockaddr_in addr;
  75. } Towho;
  76. Optype *pendops;
  77. Towho *srvlist;
  78. int npend,maxop,connected,nsrv,debug;
  79. char *ldap_ops[]={"ADD","DEL","MODRDN","MOD ","RESULT","NONE",NULL};
  80. /*
  81. * To map internal values to LDAP_REQ
  82. */
  83. int ldap_val[]={LDAP_REQ_ADD,LDAP_REQ_DELETE,LDAP_REQ_MODRDN,LDAP_REQ_MODIFY};
  84. get_op_par(char *s,Optype *op)
  85. {
  86. char *t;
  87. int i;
  88. /*
  89. * Provided they do not change dsservd's log format, this should work
  90. * Magic numbers are the length of the lookup string
  91. */
  92. t=strstr(s,"conn=");
  93. for(t+=5,op->conn=0;isdigit(*t);t++)
  94. op->conn=op->conn*10+*t-'0';
  95. t=strstr(s,"op=");
  96. for(t+=3,op->op=0;isdigit(*t);t++)
  97. op->op=op->op*10+*t-'0';
  98. if(t=strstr(s,"dn="))
  99. op->dn=strdup(t+3);
  100. }
  101. open_cnx(struct sockaddr *srv)
  102. {
  103. int i,sockfd;
  104. if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
  105. {
  106. perror("Slave");
  107. exit(1);
  108. }
  109. i=1;
  110. /*
  111. * Disable TCP's Nagle algorithm
  112. */
  113. if(setsockopt(sockfd,IPPROTO_TCP, TCP_NODELAY,(void *)&i,sizeof(int))!=0)
  114. perror("Nagle");
  115. if(connect(sockfd,srv,sizeof(struct sockaddr))!=-1)
  116. return sockfd;
  117. else close(sockfd);
  118. return -1;
  119. }
  120. send_op(char* s)
  121. {
  122. int sz,i,j,ret;
  123. Optype tmp;
  124. repconfirm *result;
  125. char *t;
  126. struct pollfd pfd;
  127. get_op_par(s,&tmp);
  128. for(i=0;i<maxop;i++)
  129. /*
  130. * got a RESULT string. Try to match with known operations.
  131. */
  132. if(pendops[i].op==tmp.op && pendops[i].conn==tmp.conn)
  133. {
  134. sz=strlen(pendops[i].dn);
  135. result=(repconfirm*)malloc(sizeof(repconfirm)+sz);
  136. t=strstr(s,"err=");
  137. for(t+=4,result->res=0;isdigit(*t);t++)
  138. result->res=result->res*10+*t-'0';
  139. /*
  140. * Build packet
  141. */
  142. result->type=htonl(ldap_val[pendops[i].type]);
  143. strcpy(result->dn,pendops[i].dn+1);
  144. sz-=2;
  145. result->dn[sz]='\0';
  146. result->dnSize=htonl(sz);
  147. if(debug)
  148. printf("Sending %d %d %s\n",ntohl(result->type),result->res,result->dn);
  149. result->res=htonl(result->res);
  150. /*
  151. * find which filter applies. Note that if no filter applies, no
  152. * packets are sent
  153. */
  154. for(j=0;j<nsrv;j++)
  155. {
  156. /*
  157. * Suppose a NULL filter means everything
  158. */
  159. if(srvlist[j].filter)
  160. if(regex(srvlist[j].filter,result->dn)==NULL)
  161. continue;
  162. /*
  163. * try to write. This works if server set SO_LINGER option
  164. * with parameters l_onoff=1,l_linger=0. This means terminate
  165. * the connection sending an RST instead of FIN, so that
  166. * write() will fail on first attempt instead of second.
  167. */
  168. if(write(srvlist[j].fd,result,sizeof(repconfirm)+sz)<=0)
  169. {
  170. /*
  171. * socket was closed by peer. try again
  172. */
  173. close(srvlist[j].fd);
  174. if((srvlist[j].fd=connected=open_cnx((struct sockaddr*)&srvlist[j].addr))==-1)
  175. /*
  176. * OK, server disconnected for good
  177. */
  178. continue;
  179. if((ret=write(srvlist[j].fd,result,sizeof(repconfirm)+sz))<=0)
  180. puts("Porc!");
  181. }
  182. }
  183. /*
  184. * Copy over the operation at the end
  185. */
  186. free(pendops[i].dn);
  187. maxop--;
  188. pendops[i]=pendops[maxop];
  189. free(result);
  190. break;
  191. }
  192. if (tmp.dn != NULL)
  193. free(tmp.dn);
  194. }
  195. main(int argc, char**argv)
  196. {
  197. int i,port=16000;
  198. int sockfd,log=0;
  199. static char logline[512];
  200. char **tmp,*hn,*hp,*hf;
  201. struct hostent *serveraddr;
  202. while((i=getopt(argc,argv,"tdP:s:"))!=EOF)
  203. {
  204. switch(i)
  205. {
  206. case 't': log=1;
  207. break;
  208. case 'd': debug=1;
  209. break;
  210. case 'P':
  211. port=atoi(optarg);
  212. break;
  213. case 's':
  214. /*
  215. * pointers to hostname, host port, filter
  216. */
  217. hn=strtok(optarg,",");
  218. hp=strtok(NULL,",");
  219. hf=strtok(NULL,",");
  220. if(hf==NULL&&hp)
  221. if(*hp<'0' || *hp >'9')
  222. hf=hp;
  223. if(hn==NULL||hf==NULL)
  224. {
  225. puts("Missing parameter\n");
  226. break;
  227. }
  228. /*
  229. * Get master address, just the first.
  230. */
  231. if((serveraddr=gethostbyname(hn))==NULL)
  232. {
  233. printf("Unknown host %s\n",hn);
  234. break;
  235. }
  236. srvlist=(Towho*)realloc(srvlist,(nsrv+1)*sizeof(Towho));
  237. srvlist[nsrv].addr.sin_addr.s_addr=htonl(*((u_long*)(serveraddr->h_addr_list[0])));
  238. srvlist[nsrv].addr.sin_family=AF_INET;
  239. srvlist[nsrv].addr.sin_port=htonl((hp==hf?port:atoi(hp)));
  240. if((srvlist[nsrv].filter=regcmp(hf,NULL))==NULL)
  241. printf("Wrong REX: %s\n",hf);
  242. srvlist[nsrv].fd=open_cnx((struct sockaddr*)&srvlist[nsrv].addr);
  243. srvlist[nsrv].hname=strdup(hn);
  244. nsrv++;
  245. break;
  246. }
  247. }
  248. if(!nsrv)
  249. {
  250. if(!argv[optind])
  251. {
  252. printf("Usage: %s [-td] -P port <hostname>\n\tor %s [-td] -s <host>,[<port>,]<REGEX>\n",argv[0],argv[0]);
  253. printf("\t-t\tprints input on stdout.\n\t-d\tdebug mode.\n");
  254. exit(1);
  255. }
  256. srvlist=(Towho*)malloc(sizeof(Towho));
  257. if((serveraddr=gethostbyname(argv[optind]))==NULL)
  258. {
  259. printf("Unknown host %s\n",argv[optind]);
  260. exit(1);
  261. }
  262. srvlist[nsrv].addr.sin_addr.s_addr=htonl(*((u_long*)(serveraddr->h_addr_list[0])));
  263. srvlist[nsrv].addr.sin_family=AF_INET;
  264. srvlist[nsrv].addr.sin_port=htons(port);
  265. srvlist[nsrv].filter=NULL;
  266. srvlist[nsrv].fd=open_cnx((struct sockaddr*)&srvlist[nsrv].addr);
  267. srvlist[nsrv].hname=strdup(argv[optind]);
  268. nsrv++;
  269. }
  270. maxop=npend=0;
  271. pendops=(Optype*)malloc(sizeof(Optype)*20);
  272. /*
  273. * Ignore SIGPIPE during write()
  274. */
  275. sigset(SIGPIPE,SIG_IGN);
  276. while(fgets(logline, sizeof(logline), stdin))
  277. {
  278. if (p = strchr(logline, '\n')) {
  279. *p = 0;
  280. }
  281. if(log)
  282. puts(logline);
  283. for(tmp=ldap_ops,i=0;tmp[i];i++)
  284. if(strstr(logline,tmp[i]))
  285. break;
  286. if(i<RESULT)
  287. {
  288. get_op_par(logline,&pendops[maxop]);
  289. pendops[maxop].type=i;
  290. if(++maxop>npend)
  291. npend=maxop;
  292. if(!(npend%20))
  293. {
  294. pendops=(Optype*)realloc(pendops,sizeof(Optype)*(npend+20));
  295. memset(pendops+npend,0,sizeof(Optype)*20);
  296. }
  297. }
  298. if(i==RESULT)
  299. send_op(logline);
  300. }
  301. }
  302. /* End of file */