void Tee_init_socks() { struct tee_receiver *target = NULL; struct sockaddr *sa; int pool_idx, recv_idx, err; char dest_addr[256], dest_serv[256]; for (pool_idx = 0; pool_idx < receivers.num; pool_idx++) { for (recv_idx = 0; recv_idx < receivers.pools[pool_idx].num; recv_idx++) { target = &receivers.pools[pool_idx].receivers[recv_idx]; sa = (struct sockaddr *) &target->dest; if (sa->sa_family != 0) { if ((err = getnameinfo(sa, target->dest_len, dest_addr, sizeof(dest_addr), dest_serv, sizeof(dest_serv), NI_NUMERICHOST)) == -1) { Log(LOG_ERR, "ERROR ( %s/%s ): getnameinfo: %d\n", config.name, config.type, err); exit_plugin(1); } } target->fd = Tee_prepare_sock((struct sockaddr *) &target->dest, target->dest_len); if (config.debug) { struct host_addr recv_addr; u_char recv_addr_str[INET6_ADDRSTRLEN]; u_int16_t recv_port; sa_to_addr(&target->dest, &recv_addr, &recv_port); addr_to_str(recv_addr_str, &recv_addr); Log(LOG_DEBUG, "DEBUG ( %s/%s ): pool ID: %u :: receiver: %s :: fd: %d.\n", config.name, config.type, receivers.pools[pool_idx].id, recv_addr_str, target->fd); } } } }
void tee_plugin(int pipe_fd, struct configuration *cfgptr, void *ptr) { struct pkt_msg *msg; unsigned char *pipebuf; struct pollfd pfd; int timeout, err; int ret, num, fd; struct ring *rg = &((struct channels_list_entry *)ptr)->rg; struct ch_status *status = ((struct channels_list_entry *)ptr)->status; u_int32_t bufsz = ((struct channels_list_entry *)ptr)->bufsize; char *dataptr, dest_addr[256], dest_serv[256]; struct sockaddr dest; socklen_t dest_len; unsigned char *rgptr; int pollagain = TRUE; u_int32_t seq = 1, rg_err_count = 0; /* XXX: glue */ memcpy(&config, cfgptr, sizeof(struct configuration)); recollect_pipe_memory(ptr); pm_setproctitle("%s [%s]", "Tee Plugin", config.name); if (config.pidfile) write_pid_file_plugin(config.pidfile, config.type, config.name); /* signal handling */ signal(SIGINT, Tee_exit_now); signal(SIGUSR1, SIG_IGN); signal(SIGUSR2, SIG_IGN); signal(SIGPIPE, SIG_IGN); #if !defined FBSD4 signal(SIGCHLD, SIG_IGN); #else signal(SIGCHLD, ignore_falling_child); #endif if (config.tee_transparent && getuid() != 0) { Log(LOG_ERR, "ERROR ( %s/%s ): Transparent mode requires super-user permissions. Exiting ...\n", config.name, config.type); exit_plugin(1); } if (!config.nfprobe_receiver) { Log(LOG_ERR, "ERROR ( %s/%s ): tee_receiver is not specified. Exiting ...\n", config.name, config.type); exit_plugin(1); } memset(&dest, 0, sizeof(dest)); dest_len = sizeof(dest); Tee_parse_hostport(config.nfprobe_receiver, (struct sockaddr *)&dest, &dest_len); config.print_refresh_time = DEFAULT_TEE_REFRESH_TIME; timeout = config.print_refresh_time*1000; pipebuf = (unsigned char *) Malloc(config.buffer_size); pfd.fd = pipe_fd; pfd.events = POLLIN; setnonblocking(pipe_fd); memset(pipebuf, 0, config.buffer_size); /* Arrange send socket */ if (dest.sa_family != 0) { if ((err = getnameinfo((struct sockaddr *) &dest, dest_len, dest_addr, sizeof(dest_addr), dest_serv, sizeof(dest_serv), NI_NUMERICHOST)) == -1) { Log(LOG_ERR, "ERROR ( %s/%s ): getnameinfo: %d\n", config.name, config.type, err); exit_plugin(1); } fd = Tee_prepare_sock(&dest, dest_len); } /* plugin main loop */ for (;;) { poll_again: status->wakeup = TRUE; ret = poll(&pfd, 1, timeout); if (ret < 0) goto poll_again; switch (ret) { case 0: /* timeout */ /* reserved for future since we don't currently cache/batch/etc */ break; default: /* we received data */ read_data: if (!pollagain) { seq++; seq %= MAX_SEQNUM; if (seq == 0) rg_err_count = FALSE; } else { if ((ret = read(pipe_fd, &rgptr, sizeof(rgptr))) == 0) exit_plugin(1); /* we exit silently; something happened at the write end */ } if (((struct ch_buf_hdr *)rg->ptr)->seq != seq) { if (!pollagain) { pollagain = TRUE; goto poll_again; } else { rg_err_count++; if (config.debug || (rg_err_count > MAX_RG_COUNT_ERR)) { Log(LOG_ERR, "ERROR ( %s/%s ): We are missing data.\n", config.name, config.type); Log(LOG_ERR, "If you see this message once in a while, discard it. Otherwise some solutions follow:\n"); Log(LOG_ERR, "- increase shared memory size, 'plugin_pipe_size'; now: '%u'.\n", config.pipe_size); Log(LOG_ERR, "- increase buffer size, 'plugin_buffer_size'; now: '%u'.\n", config.buffer_size); Log(LOG_ERR, "- increase system maximum socket size.\n\n"); } seq = ((struct ch_buf_hdr *)rg->ptr)->seq; } } pollagain = FALSE; memcpy(pipebuf, rg->ptr, bufsz); if ((rg->ptr+bufsz) >= rg->end) rg->ptr = rg->base; else rg->ptr += bufsz; msg = (struct pkt_msg *) (pipebuf+sizeof(struct ch_buf_hdr)); while (((struct ch_buf_hdr *)pipebuf)->num) { Tee_send(msg, &dest, fd); ((struct ch_buf_hdr *)pipebuf)->num--; if (((struct ch_buf_hdr *)pipebuf)->num) { dataptr = (unsigned char *) msg; dataptr += PmsgSz; msg = (struct pkt_msg *) dataptr; } } goto read_data; } } }