int tc_nl_socket_init() { int fd, rcvbuf; unsigned char buf[128]; struct nlmsghdr *nl_header; struct sockaddr_nl addr; struct ipq_mode_msg *mode_data; rcvbuf = 1048576; fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_FIREWALL); if (fd == -1) { tc_log_info(LOG_ERR, errno, "Create netlink socket failed"); return TC_INVALID_SOCKET; } if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)) == -1) { tc_log_info(LOG_ERR, errno, "Set netlink socket(%d) recvbuf to (%d) failed", fd, rcvbuf); return TC_INVALID_SOCKET; } tc_socket_set_nonblocking(fd); tc_memzero(&addr, sizeof(addr)); tc_memzero(&buf, 128); addr.nl_family = AF_NETLINK; nl_header = (struct nlmsghdr *) buf; /* It must be ipq_peer_msg, not ipq_mode_msg */ nl_header->nlmsg_len = NLMSG_LENGTH(sizeof(struct ipq_peer_msg)); nl_header->nlmsg_flags = NLM_F_REQUEST; nl_header->nlmsg_type = IPQM_MODE; nl_header->nlmsg_pid = getpid(); mode_data = NLMSG_DATA(nl_header); mode_data->value = IPQ_COPY_PACKET; mode_data->range = 65536; if (sendto(fd, (void *) nl_header, nl_header->nlmsg_len, 0, (struct sockaddr *) &addr, sizeof(struct sockaddr_nl)) == -1) { tc_log_info(LOG_ERR, errno, "Set netlink socket(%d) mode failed, " "check if ip queue is run", fd); return TC_INVALID_SOCKET; } return fd; }
/* * retrieve target addresses * format * 192.168.0.1:80-192.168.0.2:8080,192.168.0.1:8080-192.168.0.3:80 */ static int retr_target_addrs(char *raw_tf, transfer_maps_t *tf) { int i; char *p, *seq; if (raw_tf == NULL) { tc_log_info(LOG_ERR, 0, "it must have -x argument"); fprintf(stderr, "no -x argument\n"); return -1; } for (tf->num = 1, p = raw_tf; *p; p++) { if (*p == ',') { tf->num++; } } tf->map = tc_palloc(clt_settings.pool, tf->num * sizeof(transfer_map_t *)); if (tf->map == NULL) { return -1; } tc_memzero(tf->map, tf->num * sizeof(transfer_map_t *)); for (i = 0; i < tf->num; i++) { tf->map[i] = tc_palloc(clt_settings.pool, sizeof(transfer_map_t)); if (tf->map[i] == NULL) { return -1; } tc_memzero(tf->map[i], sizeof(transfer_map_t)); } p = raw_tf; i = 0; for ( ;; ) { if ((seq = strchr(p, ',')) == NULL) { if (parse_target(tf->map[i++], p) == -1) { return -1; } break; } else { *seq = '\0'; if (parse_target(tf->map[i++], p) == -1) { return -1; } *seq = ','; p = seq + 1; } } return 0; }
int tc_socket_listen(int fd, const char *bind_ip, uint16_t port) { socklen_t len; struct sockaddr_in local_addr; tc_memzero(&local_addr, sizeof(local_addr)); local_addr.sin_port = ntohs(port); local_addr.sin_family = AF_INET; if (bind_ip) { /* set bind ip for security reasons */ inet_aton(bind_ip, &local_addr.sin_addr); } len = (socklen_t) sizeof(local_addr); if (bind(fd, (struct sockaddr *) &local_addr, len) == -1) { tc_log_info(LOG_ERR, errno, "Bind socket(%d) to port:%d failed", fd, port); return TC_ERROR; } if (listen(fd, 5) == -1) { tc_log_info(LOG_ERR, errno, "Listen socket(%d) failed", fd); return TC_ERROR; } return TC_OK; }
int tc_socket_connect(int fd, uint32_t ip, uint16_t port) { socklen_t len; struct sockaddr_in remote_addr; tc_memzero(&remote_addr, sizeof(remote_addr)); remote_addr.sin_family = AF_INET; remote_addr.sin_addr.s_addr = ip; remote_addr.sin_port = htons(port); len = (socklen_t) (sizeof(remote_addr)); if (connect(fd, (struct sockaddr *) &remote_addr, len) == -1) { tc_log_info(LOG_ERR, errno, "Can not connect to remote server(%s:%d)", inet_ntoa(remote_addr.sin_addr), port); tc_socket_close(fd); return TC_ERROR; } else { tc_log_info(LOG_INFO, 0, "connect to remote server(%s:%d)", inet_ntoa(remote_addr.sin_addr), port); return TC_OK; } }
/* retrieve ip addresses */ static int retrieve_ip_addr() { int count = 0; char tmp[32]; size_t len; uint32_t address; const char *split, *p; tc_memzero(tmp, 32); p = srv_settings.raw_ip_list; while (true) { split = strchr(p, ','); if (split != NULL) { len = (size_t) (split - p); } else { len = strlen(p); } strncpy(tmp, p, len); address = inet_addr(tmp); srv_settings.passed_ips.ips[count++] = address; if (count == MAX_ALLOWED_IP_NUM) { tc_log_info(LOG_WARN, 0, "reach the limit for passing firewall"); break; } if (split == NULL) { break; } else { p = split + 1; } tc_memzero(tmp, 32); } srv_settings.passed_ips.num = count; return 1; }
static bool send_version(int fd) { msg_clt_t msg; tc_memzero(&msg, sizeof(msg_clt_t)); msg.type = htons(INTERNAL_VERSION); if (tc_socket_snd(fd, (char *) &msg, MSG_CLT_SIZE) == TC_ERR) { tc_log_info(LOG_ERR, 0, "send version error:%d", fd); return false; } return true; }
static int read_conf_file() { #if (TC_PLUGIN) tc_buf_t b; tc_conf_file_t conf_file; tc_memzero(&conf_file, sizeof(tc_conf_file_t)); tc_memzero(&b, sizeof(tc_buf_t)); clt_settings.cf = tc_palloc(clt_settings.pool, sizeof(tc_conf_t)); conf_file.file.fd = -1; conf_file.line = 0; clt_settings.cf->conf_file = &conf_file; clt_settings.cf->pool = clt_settings.pool; clt_settings.cf->args = tc_array_create(clt_settings.pool, 10, sizeof(tc_str_t)); if (clt_settings.conf_file == NULL) { clt_settings.conf_file = TC_CONF_PATH; } clt_settings.conf_file = tc_conf_full_name(clt_settings.pool, TC_PREFIX, clt_settings.conf_file); if (tc_conf_parse(clt_settings.plugin, clt_settings.pool, clt_settings.cf, clt_settings.conf_file) != TC_OK) { return TC_ERR; } clt_settings.cf->conf_file = NULL; #endif return TC_OK; }
int tc_raw_socket_snd(int fd, void *buf, size_t len, uint32_t ip) { ssize_t send_len, offset = 0, num_bytes; const char *ptr; struct sockaddr_in dst_addr; if (fd > 0) { tc_memzero(&dst_addr, sizeof(struct sockaddr_in)); dst_addr.sin_family = AF_INET; dst_addr.sin_addr.s_addr = ip; ptr = buf; /* * The output packet will take a special path of IP layer * (raw_sendmsg->raw_send_hdrinc->NF_INET_LOCAL_OUT->...). * No IP fragmentation will take place if needed. * This means that a raw packet larger than the MTU of the * interface will probably be discarded. Instead ip_local_error(), * which does general sk_buff cleaning, is called and an * error EMSGSIZE is returned. */ do { num_bytes = len - offset; send_len = sendto(fd, ptr + offset, num_bytes, 0, (struct sockaddr *) &dst_addr, sizeof(dst_addr)); if (send_len >= 0) { offset += send_len; } else { if (errno == EINTR) { tc_log_info(LOG_NOTICE, errno, "raw fd:%d EINTR", fd); } else if (errno == EAGAIN) { tc_log_info(LOG_NOTICE, errno, "raw fd:%d EAGAIN", fd); } else { tc_log_info(LOG_ERR, errno, "raw fd:%d", fd); tc_socket_close(fd); return TC_ERR; } } } while (offset < (ssize_t) len); } return TC_OK; }
static int proc_when_sess_created(tc_sess_t *s) { tc_mysql_session *data = s->data; if (data == NULL) { data = (tc_mysql_session *) tc_pcalloc(s->pool, sizeof(tc_mysql_session)); if (data) { s->data = data; } } else { tc_memzero(data, sizeof(tc_mysql_session)); } return TC_OK; }
int tc_socket_listen(int fd, const char *bind_ip, uint16_t port) { int opt, ret; socklen_t len; struct sockaddr_in local_addr; tc_memzero(&local_addr, sizeof(local_addr)); local_addr.sin_port = ntohs(port); local_addr.sin_family = AF_INET; if (bind_ip) { /* set bind ip for security reasons */ inet_aton(bind_ip, &local_addr.sin_addr); } opt = 1; ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); if (ret == -1) { tc_log_info(LOG_ERR, errno, "setsockopt error"); return TC_INVALID_SOCK; } len = (socklen_t) sizeof(local_addr); if (bind(fd, (struct sockaddr *) &local_addr, len) == -1) { tc_log_info(LOG_ERR, errno, "Bind socket(%d) to port:%u failed", fd, port); fprintf(stderr, "Bind socket(%d) to port:%u failed\n", fd, port); return TC_ERR; } if (listen(fd, 5) == -1) { tc_log_info(LOG_ERR, errno, "Listen socket(%d) failed", fd); fprintf(stderr, "Listen socket(%d) failed\n", fd); return TC_ERR; } return TC_OK; }
int set_signal_handler(signal_t *signals) { int status; signal_t *sig; struct sigaction sa; for (sig = signals; sig->signo != 0; sig++) { tc_memzero(&sa, sizeof(sa)); sa.sa_handler = sig->handler; sa.sa_flags = sig->flags; sigemptyset(&sa.sa_mask); status = sigaction(sig->signo, &sa, NULL); if (status < 0) { tc_log_info(LOG_ERR, errno, "sigaction(%s) failed", sig->signame); return -1; } } return 0; }