/* process_packet: * Callback which processes a packet captured by libpcap. */ void process_packet(u_char *user, const struct pcap_pkthdr *hdr, const u_char *pkt) { struct tcphdr tcp; int off, len, delta; connection *C, c; struct sockaddr_storage src, dst; struct sockaddr *s, *d; uint8_t proto; s = (struct sockaddr *)&src; d = (struct sockaddr *)&dst; if (handle_link_layer(&datalink_info, pkt, hdr->caplen, &proto, &off)) return; if (layer3_find_tcp(pkt, proto, &off, s, d, &tcp)) return; len = hdr->caplen - off; /* XXX fragmented packets and other nasties. */ /* try to find the connection slot associated with this. */ C = find_connection(s, d); /* no connection at all, so we need to allocate one. */ if (!C) { log_msg(LOG_INFO, "new connection: %s", connection_string(s,d)); C = alloc_connection(); *C = connection_new(s, d); /* This might or might not be an entirely new connection (SYN flag * set). Either way we need a sequence number to start at. */ (*C)->isn = ntohl(tcp.th_seq); } /* Now we need to process this segment. */ c = *C; delta = 0;/*tcp.syn ? 1 : 0;*/ /* NB (STD0007): * SEG.LEN = the number of octets occupied by the data in the * segment (counting SYN and FIN) */ #if 0 if (tcp.syn) /* getting a new isn. */ c->isn = htonl(tcp.seq); #endif if (tcp.th_flags & TH_RST) { /* Looks like this connection is bogus, and so might be a * connection going the other way. */ log_msg(LOG_INFO, "connection reset: %s", connection_string(s, d)); connection_delete(c); *C = NULL; if ((C = find_connection(d, s))) { connection_delete(*C); *C = NULL; } return; } if (len > 0) { /* We have some data in the packet. If this data occurred after * the first data we collected for this connection, then save it * so that we can look for images. Otherwise, discard it. */ unsigned int offset; offset = ntohl(tcp.th_seq); /* Modulo 2**32 arithmetic; offset = seq - isn + delta. */ if (offset < (c->isn + delta)) offset = 0xffffffff - (c->isn + delta - offset); else offset -= c->isn + delta; if (offset > c->len + WRAPLEN) { /* Out-of-order packet. */ log_msg(LOG_INFO, "out of order packet: %s", connection_string(s, d)); } else { connection_push(c, pkt + off, offset, len); extract_media(c); } } if (tcp.th_flags & TH_FIN) { /* Connection closing; mark it as closed, but let sweep_connections * free it if appropriate. */ log_msg(LOG_INFO, "connection closing: %s, %d bytes transferred", connection_string(s, d), c->len); c->fin = 1; } /* sweep out old connections */ sweep_connections(); }
//----------------------------------------------------------------------------- // TODO: determine level of detail for return value, i.e. bool or enum connection_c::error_e connection_c::open( void ) { // sanity checks if( _open ) return ERROR_NONE; assert( _role != UNDEFINED ); if( _role == CLIENT || _role == ROUTER ) { // if client or router, build a context // Note: for DEALER or WORKER, the context was supplied in construction _context = zmq_ctx_new(); if( _context == NULL ) { return ERROR_CONTEXT; // Note: no error values are defined for zmq_ctx_new } } // open a socket if( _role == CLIENT ) { _socket = zmq_socket( _context, ZMQ_REQ ); } else if( _role == ROUTER ) { _socket = zmq_socket( _context, ZMQ_ROUTER ); } else if( _role == DEALER ) { _socket = zmq_socket( _context, ZMQ_DEALER ); } else if( _role == WORKER ) { _socket = zmq_socket( _context, ZMQ_REP ); /* } else if( _role == IPC_SERVER ) { _socket = zmq_socket( _context, ZMQ_PAIR ); } else if( _role == IPC_CLIENT ) { _socket = zmq_socket( _context, ZMQ_PAIR ); */ } else { // Note: sanity checks should guarantee never getting here. return ERROR_SOCKET; } // validate socket creation if( _socket == NULL ) { if( errno == EINVAL ) { // the requested socket type is invalid return ERROR_SOCKET; } else if( errno == EFAULT ) { // the provided context is invalid return ERROR_CONTEXT; } else if( errno == EMFILE ) { // the limit on the number of open sockets has been reached return ERROR_LIMIT; } else if( errno == ETERM ) { // the context specified was terminated return ERROR_CONTEXT; } else { // Note: above should trap specifics, but if fall through then return // a socket error return ERROR_SOCKET; } } //if( _role == CLIENT || _role == WORKER || _role == IPC_CLIENT ) { if( _role == CLIENT || _role == WORKER ) { // if client or worker, connect to the socket if( zmq_connect( _socket, connection_string().c_str() ) == -1 ) { if( errno == EINVAL ) { // endpoint invalid return ERROR_ADDRESS; } else if( errno == EPROTONOSUPPORT ) { // transport protocol is not supported return ERROR_SOCKET; } else if( errno == ENOCOMPATPROTO ) { // transport protocol incompatible with socket return ERROR_SOCKET; } else if( errno == ETERM ) { // zeromq context was terminated return ERROR_CONTEXT; } else if( errno == ENOTSOCK ) { // socket is invalid return ERROR_SOCKET; } else if( errno == EMTHREAD ) { // no I/O thread available return ERROR_CONTEXT; } else { // Note: above should trap specifics, but if fall through then return // a socket error return ERROR_SOCKET; } } //} else if( _role == ROUTER || _role == DEALER || _role == IPC_SERVER ) { } else if( _role == ROUTER || _role == DEALER ) { // if router or dealer, bind to the socket if( zmq_bind( _socket, connection_string().c_str() ) == -1 ) { if( errno == EINVAL ) { // endpoint invalid return ERROR_ADDRESS; } else if( errno == EPROTONOSUPPORT ) { // transport protocol is not supported return ERROR_SOCKET; } else if( errno == ENOCOMPATPROTO ) { // transport protocol incompatible with socket return ERROR_SOCKET; } else if( errno == EADDRINUSE ) { // requested address already in use return ERROR_ADDRESS; } else if( errno == EADDRNOTAVAIL ) { // requested address was not local return ERROR_ADDRESS; } else if( errno == ENODEV ) { // requested address specifies a nonexistent interface return ERROR_ADDRESS; } else if( errno == ETERM ) { // zeromq context was terminated return ERROR_CONTEXT; } else if( errno == ENOTSOCK ) { // socket is invalid return ERROR_SOCKET; } else if( errno == EMTHREAD ) { // no I/O thread available return ERROR_CONTEXT; } else { // Note: above should trap specifics, but if fall through then return // a socket error return ERROR_SOCKET; } } } // otherwise success, socket is open _open = true; return ERROR_NONE; }
connection::pointer node::get_connection(uint64_t db) { auto cn = m_route.find(db); VLOG(2) << "connection: " << cn->connection_string() << ", db: " << db; return cn; }