示例#1
0
static int accept_cb(tcp_server_stream_t *listen_stream)
{
    struct sockaddr_in remote_addr;
    struct epoll_event event;
    socklen_t          addr_len;
    int                sock_fd;
    tcp_server_t      *server;
    tcp_server_stream_t      *stream;

    bzero(&remote_addr, sizeof(remote_addr));
    addr_len = sizeof(struct sockaddr_in); 

    sock_fd = accept(listen_stream->sock_fd, (struct sockaddr *)&remote_addr, &addr_len);
    if (sock_fd < 0) {
        if (EAGAIN != errno) {
            log_error("accept error, %s.", strerror(errno)); 
            return 0;
        }
        else {
            log_info("no connection for accept."); 
            return 1;
        }
    }

    log_debug("new connection comes, fd: %d.", sock_fd);
    if (!set_non_blocking(sock_fd)) {
        log_error("set sock_fd: %d failed.", sock_fd);
        close(sock_fd);
        return 0;
    }

    stream = get_idle_tcp_stream(server);
    if (NULL == stream) {
        log_error("no idle stream.");
        return 0;
    }

    tcp_stream_init(server, stream, sock_fd, &remote_addr); 
    add_stream_into_busy_list(server, stream);

    /* 将当前sock fd添加到epoll中 */
    bzero(&event, sizeof(event));
    event.data.fd  = sock_fd;
    event.data.ptr = stream;
    event.events   = EPOLLIN | EPOLLET;

    if (epoll_ctl(server->epoll_fd, EPOLL_CTL_ADD, sock_fd, &event) < 0) {
        log_error("accept_cb, EPOLL_CTL_ADD error, %s.", strerror(errno)); 
        tcp_stream_close(stream);
        return 0;
    }
    server->active_stream_num++;

    return 1;
}
示例#2
0
tcp_server_t *tcp_server_create(int port, int max_conn)
{
    tcp_server_t *server = NULL;
    tcp_server_stream_t *stream = NULL;
    int max_conn_count = TCP_MAX_STREAM_NUM;
    int i = 0;
    struct sockaddr_in server_addr;
    struct epoll_event event;

    server = (tcp_server_t *)malloc(sizeof(tcp_server_t));
    if (NULL == server) {
        goto error; 
    }
    bzero(server, sizeof(tcp_server_t));
    server->rcv_cb = rcv_cb_default;
    server->snd_cb = snd_cb_default;
    
    server->port = port;

    if (max_conn > 0) {
        max_conn_count = max_conn; 
    }

    /* 创建并发连接结构 */
    server->streams = (tcp_server_stream_t *)malloc(sizeof(tcp_server_stream_t) * max_conn_count);
    if (NULL == server->streams) {
        log_error("malloc for server->streams failed.");
        goto error;
    }
    bzero(server->streams, sizeof(tcp_server_stream_t) * max_conn_count);
    server->stream_num = max_conn_count;

    /* idle stream链表初始化 */
    for (i = 0; i < max_conn_count; i++) {
        server->streams[i].index = i;
        add_stream_into_idle_list(server, &server->streams[i]); 
    }

    /* 创建listen socket */
    server->listen_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (-1 == server->listen_fd) {
        log_error("create socket failed, %s", strerror(errno));
        goto error;
    }

    /* 设置为非阻塞 */
    if (!set_non_blocking(server->listen_fd)){
        log_error("set_non_blocking failed.");
        goto error;
    }

    /* 设置地址重用 */
    if (!set_reuse_addr(server->listen_fd)) {
        log_error("set reuse addr failed.");
        goto error;
    }

    /* 绑定端口 */
    bzero(&server_addr, sizeof(struct sockaddr_in));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    server_addr.sin_port        = htons(server->port);
    if (bind(server->listen_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
        log_error("bind server addr failed, %s", strerror(errno));
        goto error;
    }

    /* 设置监听 */
    if (listen(server->listen_fd, TCP_MAX_LISTEN_NUM) < 0) {
        log_error("listen failed, %s", strerror(errno));
        goto error;
    }

    /* 创建epoll句柄 */
    server->epoll_fd = epoll_create(TCP_MAX_CONNECT_NUM);
    if (server->epoll_fd < 0) {
        log_error("epoll_create failed, %s", strerror(errno));
        goto error;
    }

    /* 获取空闲的stream */
    stream = get_idle_tcp_stream(server);
    if (NULL == stream) {
        log_error("get_idle_tcp_stream for listen stream failed.");
        goto error;
    }

    /* 将listen fd加入epoll */
    bzero(&event, sizeof(event));
    event.data.fd  = server->listen_fd;
    event.data.ptr = stream;
    event.events   = EPOLLIN | EPOLLET;

    /* 创建listen stream */
    tcp_stream_init(server, stream, server->listen_fd, NULL);
    stream->snd_cb = NULL; 
    stream->rcv_cb = accept_cb;

    add_stream_into_busy_list(server, stream);

    return server;

error:
    tcp_server_destroy(server); 

    return NULL;
}
示例#3
0
int main(int argc, char **argv)  {

        int arg,ret;
	char *configfile;
	char pcapfile[256];

	// Load default config
	init_config();

        // Set the signal handlers
        signal(SIGHUP, sighup_handler);
        signal(SIGINT, sigquit_handler);
        signal(SIGQUIT,sigquit_handler);


        // Parse command-line options
        while ((arg = getopt(argc, argv, "IP:i:c:f:DqvdTsr:l:u:S:")) != -1){
                switch (arg){
                        case 'f':
                                strncpy(CONFIG_PCAP_FILTER,optarg,CONFIG_MAX_CHAR);
                                break;
			case 'r':
				strncpy(pcapfile,optarg,256);
				mode_offline=1;
				break;
			case 'c':
				configfile = optarg;
				read_config(configfile);
				//dump_config();
				break;
                        case 'i':
				// Start the pcap thread
                                strncpy(CONFIG_PCAP_DEV,optarg,CONFIG_MAX_CHAR);
                                break;
                        case 'P':
				CONFIG_DIVERT_PORT=atoi(optarg);
				break;
			case 'I':
				CONFIG_DIVERT_ENABLE=1;
                                break;
                        case 'q':
                                CONFIG_LOG_STDOUT = 0;
                                break;
                        case 'u':
				strncpy(CONFIG_USER,optarg,CONFIG_MAX_CHAR);
                                break;
                        case 'l':
                                strncpy(CONFIG_LOGDIR,optarg,CONFIG_MAX_CHAR);
				if(strlen(CONFIG_LOGDIR) > 64) {
					fatal_error("Log directory is too long!");
				}
				if (access(CONFIG_LOGDIR, F_OK) == -1){
					fatal_error("Log directory does not exist");
				}
                                break;
                        case 's':
                                CONFIG_LOG_SYSLOG = 1;
                                break;
			case 'S':
                                strncpy(CONFIG_SIGFILE,optarg,CONFIG_MAX_CHAR);
				break;
			case 'T':
				CONFIG_TCP_STRICT = 0;
				break;
                        case 'v':
                                CONFIG_LOG_VERBOSE++;
                                break;
			case 'd':
				CONFIG_SHOW_TRAFFIC = 1;
				break;
                        case 'D':
				fork_to_background(); 
                                break;
                        default:
				usage();
				exit(1);
                                break;
                }
        }

	// Initialize the stats structure and the streams
	stats_init();

        // Create the list, this is to store the IP packets in which can then
        // be read by another thread. TODO: add maximum list size
        trafficlist = getRingBuffer(CONFIG_RINGBUFFER_SIZE);

        // Register the destructor
        registerListDestructor(destructor_callback,trafficlist);
        registerListIterator(traffic_analyzer,trafficlist);

	// Create the control thread first for message logging
        pthread_create(&t_control,NULL,(void*)control_loop,NULL);

	//Initialize the detection hooks
	detect_hook_init();
	tcp_stream_init();

	//Initialize the timers
	timer_init();
	timer_register_function(CONFIG_TIMER_STATS,"Stats printer",stats_show_cnt_line,NULL);
	timer_register_function(CONFIG_TIMER_TCP_CLEANER,"TCP session cleaner", tcp_clean_sessions,NULL);
	timer_register_function(CONFIG_TIMER_IPFRAG_CLEANER,"IP fragment cleaner", ip_frag_cleaner,NULL);

	//Load the signatures
	if(load_signatures(CONFIG_SIGFILE) == 1){
		usage();
		exit(1);
	}

	// Make signature index;
	init_signature_indexes();

	log_info("Signatures loaded: %d, not loaded: %d", stat_get(CNT_SIG_LOADED), stat_get(CNT_SIG_NOT_LOADED));


	// Check if root privileges are required
	if(mode_offline == 0 && getuid() != 0) {
		fprintf(stderr, "Root privileges are required, unless you specify a\n");
		fprintf(stderr, "pcap file with the '-r' option..\n");
		exit(1);
	}

	if(CONFIG_DIVERT_ENABLE) {
		log_info("Opening DIVERT socket port: %d\n",CONFIG_DIVERT_PORT);
		divert_open_socket(CONFIG_DIVERT_PORT);

		// Start the divert_listen loop
		pthread_create(&t_listener,NULL,(void*)divert_listen_loop,handle);
	} else if(mode_offline != 1) {

		// If no device was specified AND not configured then the only
		// option is to pick one using the cap library (not recommended)
		if(*CONFIG_PCAP_DEV == '0') {
			if(pcap_return_device() != NULL) {
				log_info("Picking random interface (overrule -i)");
				strncpy(CONFIG_PCAP_DEV,pcap_return_device(),CONFIG_MAX_CHAR);
			} else {
					usage();
					exit(1);
			}
		}

		// Start the sniffer thread
		handle = pcap_open_device(CONFIG_PCAP_DEV,CONFIG_PCAP_FILTER);
		pthread_create(&t_listener,NULL,(void*)pcap_listen_loop,handle);
	} else {

		// Open the file
		handle = pcap_open_file(pcapfile,CONFIG_PCAP_FILTER);
		pthread_create(&t_listener,NULL,(void*)pcap_listen_loop,handle);
	}

	// Chroot if needed
	if(CONFIG_CHROOT_ENABLE == 1) {
		if((ret = chroot(CONFIG_CHROOT_DIR)) != 0) {
			fatal_error("Chroot to \"%s\" failed: %s !",CONFIG_CHROOT_DIR, strerror(errno));
		} else {
			log_info("Chroot to directory: \"%s\" done",CONFIG_CHROOT_DIR);
		}
	}

	// Drop privileges if needed
	if(*CONFIG_USER != '0' && drop_privileges(CONFIG_USER) != 0) {
		fatal_error("Unable to drop privileges, quitting for security reasons",CONFIG_USER);
	}

	// Set the time
	gettimeofday(&startuptime,NULL);
        pthread_create(&t_analyzer,NULL,(void*)pcap_analyzer,NULL);

	if(mode_offline == 1) {
		pthread_join(t_analyzer, NULL);
	} else {
		pthread_join(t_listener,NULL);
	}

	// Control thread
	loop_control = 0;
	pthread_join(t_control, NULL);

	// And bail out
	dump_stats(stdout);
        return 0;
}