log.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. /*
  2. 3APA3A simpliest proxy server
  3. (c) 2002-2020 by Vladimir Dubrovin <3proxy@3proxy.ru>
  4. please read License Agreement
  5. */
  6. #include "proxy.h"
  7. pthread_mutex_t log_mutex;
  8. int havelog = 0;
  9. struct clientparam logparam;
  10. struct srvparam logsrv;
  11. void dolog(struct clientparam * param, const unsigned char *s){
  12. static int init = 0;
  13. if(param)param->srv->logfunc(param, s);
  14. else {
  15. if(!init){
  16. srvinit(&logsrv, &logparam);
  17. init = 1;
  18. }
  19. logstdout(&logparam, s);
  20. }
  21. }
  22. void clearstat(struct clientparam * param) {
  23. #ifdef _WIN32
  24. struct timeb tb;
  25. ftime(&tb);
  26. param->time_start = (time_t)tb.time;
  27. param->msec_start = (unsigned)tb.millitm;
  28. #else
  29. struct timeval tv;
  30. struct timezone tz;
  31. gettimeofday(&tv, &tz);
  32. param->time_start = (time_t)tv.tv_sec;
  33. param->msec_start = (tv.tv_usec / 1000);
  34. #endif
  35. param->statscli64 = param->statssrv64 = param->nreads = param->nwrites =
  36. param->nconnects = 0;
  37. }
  38. char months[12][4] = {
  39. "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  40. "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  41. };
  42. int dobuf2(struct clientparam * param, unsigned char * buf, const unsigned char *s, const unsigned char * doublec, struct tm* tm, char * format){
  43. int i, j;
  44. int len;
  45. time_t sec;
  46. unsigned msec;
  47. long timezone;
  48. unsigned delay;
  49. #ifdef _WIN32
  50. struct timeb tb;
  51. ftime(&tb);
  52. sec = (time_t)tb.time;
  53. msec = (unsigned)tb.millitm;
  54. timezone = tm->tm_isdst*60 - tb.timezone;
  55. #else
  56. struct timeval tv;
  57. struct timezone tz;
  58. gettimeofday(&tv, &tz);
  59. sec = (time_t)tv.tv_sec;
  60. msec = tv.tv_usec / 1000;
  61. #ifdef _SOLARIS
  62. timezone = -altzone / 60;
  63. #else
  64. timezone = tm->tm_gmtoff / 60;
  65. #endif
  66. #endif
  67. delay = param->time_start?((unsigned) ((sec - param->time_start))*1000 + msec) - param->msec_start : 0;
  68. *buf = 0;
  69. for(i=0, j=0; format[j] && i < 4040; j++){
  70. if(format[j] == '%' && format[j+1]){
  71. j++;
  72. switch(format[j]){
  73. case '%':
  74. buf[i++] = '%';
  75. break;
  76. case 'y':
  77. sprintf((char *)buf+i, "%.2d", tm->tm_year%100);
  78. i+=2;
  79. break;
  80. case 'Y':
  81. sprintf((char *)buf+i, "%.4d", tm->tm_year+1900);
  82. i+=4;
  83. break;
  84. case 'm':
  85. sprintf((char *)buf+i, "%.2d", tm->tm_mon+1);
  86. i+=2;
  87. break;
  88. case 'o':
  89. sprintf((char *)buf+i, "%s", months[tm->tm_mon]);
  90. i+=3;
  91. break;
  92. case 'd':
  93. sprintf((char *)buf+i, "%.2d", tm->tm_mday);
  94. i+=2;
  95. break;
  96. case 'H':
  97. sprintf((char *)buf+i, "%.2d", tm->tm_hour);
  98. i+=2;
  99. break;
  100. case 'M':
  101. sprintf((char *)buf+i, "%.2d", tm->tm_min);
  102. i+=2;
  103. break;
  104. case 'S':
  105. sprintf((char *)buf+i, "%.2d", tm->tm_sec);
  106. i+=2;
  107. break;
  108. case 't':
  109. sprintf((char *)buf+i, "%.10u", (unsigned)sec);
  110. i+=10;
  111. break;
  112. case 'b':
  113. i+=sprintf((char *)buf+i, "%u", delay?(unsigned)(param->statscli64 * 1000./delay):0);
  114. break;
  115. case 'B':
  116. i+=sprintf((char *)buf+i, "%u", delay?(unsigned)(param->statssrv64 * 1000./delay):0);
  117. break;
  118. case 'D':
  119. i+=sprintf((char *)buf+i, "%u", delay);
  120. break;
  121. case '.':
  122. sprintf((char *)buf+i, "%.3u", msec);
  123. i+=3;
  124. break;
  125. case 'z':
  126. sprintf((char *)buf+i, "%+.2ld%.2u", timezone / 60, (unsigned)(timezone%60));
  127. i+=5;
  128. break;
  129. case 'U':
  130. if(param->username && *param->username){
  131. for(len = 0; i< 4000 && param->username[len]; len++){
  132. buf[i] = param->username[len];
  133. if(param->srv->nonprintable && (buf[i] < 0x20 || strchr((char *)param->srv->nonprintable, buf[i]))) buf[i] = param->srv->replace;
  134. if(doublec && strchr((char *)doublec, buf[i])) {
  135. buf[i+1] = buf[i];
  136. i++;
  137. }
  138. i++;
  139. }
  140. }
  141. else {
  142. buf[i++] = '-';
  143. }
  144. break;
  145. case 'n':
  146. len = param->hostname? (int)strlen((char *)param->hostname) : 0;
  147. if (len > 0 && !strchr((char *)param->hostname, ':')) for(len = 0; param->hostname[len] && i < 256; len++, i++){
  148. buf[i] = param->hostname[len];
  149. if(param->srv->nonprintable && (buf[i] < 0x20 || strchr((char *)param->srv->nonprintable, buf[i]))) buf[i] = param->srv->replace;
  150. if(doublec && strchr((char *)doublec, buf[i])) {
  151. buf[i+1] = buf[i];
  152. i++;
  153. }
  154. }
  155. else {
  156. buf[i++] = '[';
  157. i += myinet_ntop(*SAFAMILY(&param->req), SAADDR(&param->req), (char *)buf + i, 64);
  158. buf[i++] = ']';
  159. }
  160. break;
  161. case 'N':
  162. if(param->service < 15) {
  163. len = (conf.stringtable)? (int)strlen((char *)conf.stringtable[SERVICES + param->service]) : 0;
  164. if(len > 20) len = 20;
  165. memcpy(buf+i, (len)?conf.stringtable[SERVICES + param->service]:(unsigned char*)"-", (len)?len:1);
  166. i += (len)?len:1;
  167. }
  168. break;
  169. case 'E':
  170. sprintf((char *)buf+i, "%.05d", param->res);
  171. i += 5;
  172. break;
  173. case 'T':
  174. if(s){
  175. for(len = 0; i<4000 && s[len]; len++){
  176. buf[i] = s[len];
  177. if(param->srv->nonprintable && (buf[i] < 0x20 || strchr((char *)param->srv->nonprintable, buf[i]))) buf[i] = param->srv->replace;
  178. if(doublec && strchr((char *)doublec, buf[i])) {
  179. buf[i+1] = buf[i];
  180. i++;
  181. }
  182. i++;
  183. }
  184. }
  185. break;
  186. case 'e':
  187. i += myinet_ntop(*SAFAMILY(&param->sinsl), SAADDR(&param->sinsl), (char *)buf + i, 64);
  188. break;
  189. case 'i':
  190. i += myinet_ntop(*SAFAMILY(&param->sincl), SAADDR(&param->sincl), (char *)buf + i, 64);
  191. break;
  192. case 'C':
  193. i += myinet_ntop(*SAFAMILY(&param->sincr), SAADDR(&param->sincr), (char *)buf + i, 64);
  194. break;
  195. case 'R':
  196. i += myinet_ntop(*SAFAMILY(&param->sinsr), SAADDR(&param->sinsr), (char *)buf + i, 64);
  197. break;
  198. case 'Q':
  199. i += myinet_ntop(*SAFAMILY(&param->req), SAADDR(&param->req), (char *)buf + i, 64);
  200. break;
  201. case 'p':
  202. sprintf((char *)buf+i, "%hu", ntohs(*SAPORT(&param->srv->intsa)));
  203. i += (int)strlen((char *)buf+i);
  204. break;
  205. case 'c':
  206. sprintf((char *)buf+i, "%hu", ntohs(*SAPORT(&param->sincr)));
  207. i += (int)strlen((char *)buf+i);
  208. break;
  209. case 'r':
  210. sprintf((char *)buf+i, "%hu", ntohs(*SAPORT(&param->sinsr)));
  211. i += (int)strlen((char *)buf+i);
  212. break;
  213. case 'q':
  214. sprintf((char *)buf+i, "%hu", ntohs(*SAPORT(&param->req)));
  215. i += (int)strlen((char *)buf+i);
  216. break;
  217. case 'L':
  218. sprintf((char *)buf+i, "%"PRINTF_INT64_MODIFIER"u", param->cycles);
  219. i += (int)strlen((char *)buf+i);
  220. break;
  221. case 'I':
  222. sprintf((char *)buf+i, "%"PRINTF_INT64_MODIFIER"u", param->statssrv64);
  223. i += (int)strlen((char *)buf+i);
  224. break;
  225. case 'O':
  226. sprintf((char *)buf+i, "%"PRINTF_INT64_MODIFIER"u", param->statscli64);
  227. i += (int)strlen((char *)buf+i);
  228. break;
  229. case 'h':
  230. sprintf((char *)buf+i, "%d", param->redirected);
  231. i += (int)strlen((char *)buf+i);
  232. break;
  233. case '1':
  234. case '2':
  235. case '3':
  236. case '4':
  237. case '5':
  238. case '6':
  239. case '7':
  240. case '8':
  241. case '9':
  242. {
  243. int k, pmin=0, pmax=0;
  244. for (k = j; isnumber(format[k]); k++);
  245. if(format[k] == '-' && isnumber(format[k+1])){
  246. pmin = atoi(format + j) - 1;
  247. k++;
  248. pmax = atoi(format + k) -1;
  249. for (; isnumber(format[k]); k++);
  250. j = k;
  251. }
  252. if(!s || format[k]!='T') break;
  253. for(k = 0, len = 0; s[len] && i < 4000; len++){
  254. if(isspace(s[len])){
  255. k++;
  256. while(isspace(s[len+1]))len++;
  257. if(k == pmin) continue;
  258. }
  259. if(k>=pmin && k<=pmax) {
  260. buf[i] = s[len];
  261. if(param->srv->nonprintable && (buf[i] < 0x20 || strchr((char *)param->srv->nonprintable, buf[i]))) buf[i] = param->srv->replace;
  262. if(doublec && strchr((char *)doublec, buf[i])) {
  263. buf[i+1] = buf[i];
  264. i++;
  265. }
  266. i++;
  267. }
  268. }
  269. break;
  270. }
  271. default:
  272. buf[i++] = format[j];
  273. }
  274. }
  275. else buf[i++] = format[j];
  276. }
  277. buf[i] = 0;
  278. return i;
  279. }
  280. int dobuf(struct clientparam * param, unsigned char * buf, const unsigned char *s, const unsigned char * doublec){
  281. struct tm* tm;
  282. int i;
  283. char * format;
  284. time_t t;
  285. time(&t);
  286. if(!param) return 0;
  287. if(param->trafcountfunc)(*param->trafcountfunc)(param);
  288. format = param->srv->logformat?(char *)param->srv->logformat : DEFLOGFORMAT;
  289. tm = (*format == 'G' || *format == 'g')?
  290. gmtime(&t) : localtime(&t);
  291. i = dobuf2(param, buf, s, doublec, tm, format + 1);
  292. clearstat(param);
  293. return i;
  294. }
  295. void lognone(struct clientparam * param, const unsigned char *s) {
  296. if(param->trafcountfunc)(*param->trafcountfunc)(param);
  297. clearstat(param);
  298. }
  299. void logstdout(struct clientparam * param, const unsigned char *s) {
  300. FILE *log;
  301. unsigned char tmpbuf[8192];
  302. dobuf(param, tmpbuf, s, NULL);
  303. log = param->srv->stdlog?param->srv->stdlog:conf.stdlog?conf.stdlog:stdout;
  304. if(!param->nolog)if(fprintf(log, "%s\n", tmpbuf) < 0) {
  305. perror("printf()");
  306. };
  307. if(log != conf.stdlog)fflush(log);
  308. }
  309. #ifndef _WIN32
  310. void logsyslog(struct clientparam * param, const unsigned char *s) {
  311. unsigned char tmpbuf[8192];
  312. dobuf(param, tmpbuf, s, NULL);
  313. if(!param->nolog)syslog(LOG_INFO, "%s", tmpbuf);
  314. }
  315. #endif