void HandlePacket() #endif { int status; if (iv.drop) { #ifndef IPFW status = ipq_set_verdict(ipqh, m->packet_id, NF_DROP, 0, NULL); if (status < 0) { ipq_perror("NF_DROP: "); } #endif if (iv.reject) { #ifndef IPFW if(pv.layer2_resets) { RejectLayer2(m); } else #endif { RejectSocket(); } } } #ifndef IPFW else if (!iv.replace) { status = ipq_set_verdict(ipqh, m->packet_id, NF_ACCEPT, 0, NULL); if (status < 0) { ipq_perror("NF_ACCEPT: "); } } else { status = ipq_set_verdict(ipqh, m->packet_id, NF_ACCEPT, m->data_len, m->payload); if (status < 0) { ipq_perror("NF_ACCEPT: "); } } #endif }
void * _pkg_reinject() { struct list_head *pos; packet_list_t *element; int is_first = 1; static unsigned int count = 0; do { usleep(100); if (!list_empty(&pkg_list)) { if (is_first) { is_first = 0; //usleep(200000); //sleep(2); printf("receive number packets in delay: %d\n", count_packet); } pos = pkg_list.next; element = list_entry(pos, packet_list_t, list); ipq_set_verdict(h, element->pmsg->packet_id, NF_ACCEPT, 0, NULL); printf("Sending packet id = %lu, number packet = %u \n", element->pmsg->packet_id, ++count); usleep(5000); // 5ms send 1 pkg list_del(pos); SAFE_FREE(element); } } while (1); }
// This is called randomly, atleast once every 100mS int BackgroundProcessing(void){ long PacketAge; int Queue, i; // Get current time struct timeval NowTime; gettimeofday(&NowTime, NULL); // Wait for access to the packet queue pthread_mutex_lock(&PacketQueueMutex); for(Queue = 0; Queue < PacketQueues; Queue++){ // Loop while(PacketQueueHead[Queue] != PacketQueueTail[Queue]){ // Work out age in mS PacketAge = (NowTime.tv_sec - ((ipq_packet_msg_t *)&PacketQueue[Queue][PacketQueueTail[Queue] * sizeof(struct ipq_packet_msg)])->timestamp_sec) * 1000; if(NowTime.tv_usec < ((ipq_packet_msg_t *)&PacketQueue[Queue][PacketQueueTail[Queue] * sizeof(struct ipq_packet_msg)])->timestamp_usec) PacketAge += (1000000 - ((ipq_packet_msg_t *)&PacketQueue[Queue][PacketQueueTail[Queue] * sizeof(struct ipq_packet_msg)])->timestamp_usec + NowTime.tv_usec) / 1000; else PacketAge += (NowTime.tv_usec - ((ipq_packet_msg_t *)&PacketQueue[Queue][PacketQueueTail[Queue] * sizeof(struct ipq_packet_msg)])->timestamp_usec) / 1000; // If the packet is old if(PacketAge > STALETIME){ // Drop the packet ipq_set_verdict(hIpq, ((ipq_packet_msg_t *)&PacketQueue[Queue][PacketQueueTail[Queue] * sizeof(struct ipq_packet_msg)])->packet_id, NF_DROP, 0, NULL); // Move the Tail offset PacketQueueTail[Queue]++; if(PacketQueueTail[Queue] >= Config.Queue) PacketQueueTail[Queue] = 0; } else{ // As the queue should be chronological, we can assume if this // packet is not too old, later ones won't be either break; } } } // Release access to the packet queue pthread_mutex_unlock(&PacketQueueMutex); // Delete old connections from contrack for(i = 0; i < MaxConTrack; i++){ // If more than 30s since last packet if(Age(ConTrack[i].LastTime) > 30000 && ConTrack[i].Flags & CT_FlagValid){ // Clear the valid flag ConTrack[i].Flags &= ~CT_FlagValid; } } return 1; }
int SendPackets(int MaxPackets, int MaxBytes){ int Queue, Packets, Bytes, PacketBytes; // Clear counts Packets = 0; Bytes = 0; // Wait for access to the packet queue pthread_mutex_lock(&PacketQueueMutex); // Loop thorugh each queue for(Queue = 0; Queue < PacketQueues; Queue++){ // Loop for as many packets/bytes as we're allowed to send while(PacketQueueHead[Queue] != PacketQueueTail[Queue]){ // Check if we'd go over the packet limit if(Packets + 1 > MaxPackets) break; PacketBytes = ((ipq_packet_msg_t *)&PacketQueue[Queue][PacketQueueTail[Queue] * sizeof(struct ipq_packet_msg)])->data_len; // Check if we'd go over the byte limit if(Bytes + PacketBytes > MaxBytes) break; // Send the oldest packet ipq_set_verdict(hIpq, ((ipq_packet_msg_t *)&PacketQueue[Queue][PacketQueueTail[Queue] * sizeof(struct ipq_packet_msg)])->packet_id, NF_ACCEPT, 0, NULL); // Add to running totals Packets++; Bytes += PacketBytes; // Store stats ClientStats.Packets[Queue]++; ClientStats.Bytes[Queue] += PacketBytes; ClientStats.BytesAvg[Queue] += PacketBytes; // Move the Tail offset PacketQueueTail[Queue]++; if(PacketQueueTail[Queue] >= Config.Queue) PacketQueueTail[Queue] = 0; } } // Release access to the packet queue pthread_mutex_unlock(&PacketQueueMutex); return 1; }
static void ip_noise_delayer_release_function(ip_noise_message_t * m, void * context) { #ifndef __KERNEL__ struct ipq_handle * h = (struct ipq_handle *)context; #else #define h 5 #endif int status; status = ipq_set_verdict(h, m->m->packet_id, NF_ACCEPT, 0, NULL); if (status < 0) { die(h); } free(m); }
static int ipq_receive_peer(ipq_queue_t *q, ipq_peer_msg_t *m, unsigned char type, unsigned int len) { int status = 0; int busy; spin_lock_bh(&q->lock); busy = (q->terminate || q->flushing); spin_unlock_bh(&q->lock); if (busy) return -EBUSY; if (len < sizeof(ipq_peer_msg_t)) return -EINVAL; switch (type) { case IPQM_MODE: switch (m->msg.mode.value) { case IPQ_COPY_META: q->peer.copy_mode = IPQ_COPY_META; q->peer.copy_range = 0; break; case IPQ_COPY_PACKET: q->peer.copy_mode = IPQ_COPY_PACKET; q->peer.copy_range = m->msg.mode.range; if (q->peer.copy_range > 0xFFFF) q->peer.copy_range = 0xFFFF; break; default: status = -EINVAL; } break; case IPQM_VERDICT: if (m->msg.verdict.value > NF_MAX_VERDICT) status = -EINVAL; else status = ipq_set_verdict(q, &m->msg.verdict, len - sizeof(*m)); break; default: status = -EINVAL; } return status; }
int main(int argc, char **argv) { int status; unsigned char buf[BUFSIZE]; struct ipq_handle *h; h = ipq_create_handle(0, PF_INET); if (!h) die(h); status = ipq_set_mode(h, IPQ_COPY_PACKET, BUFSIZE); if (status < 0) die(h); do { status = ipq_read(h, buf, BUFSIZE, 0); if (status < 0) die(h); switch (ipq_message_type(buf)) { case NLMSG_ERROR: fprintf(stderr, "Received error message %d\n", ipq_get_msgerr(buf)); break; case IPQM_PACKET: ipq_packet_msg_t *m = ipq_get_packet(buf); struct iphdr *ip = (struct iphdr*) m->payload; struct tcphdr *tcp = (struct tcphdr*) (m->payload + (4 * ip->ihl)); int port = htons(tcp->dest); status = ipq_set_verdict(h, m->packet_id, NF_ACCEPT, 0, NULL); if (status < 0) die(h); break; default: fprintf(stderr, "Unknown message type!\n"); break; } } while (1); ipq_destroy_handle(h); return 0; }
ip_noise_arbitrator_packet_logic_t * main_init_module( ip_noise_arbitrator_iface_t * * iface_ptr ) #endif { #ifndef __KERNEL__ int status; unsigned char message[IP_NOISE_MESSAGE_BUFSIZE]; struct ipq_handle * h; ip_noise_messages_queue_t * packets_to_arbitrate_queue; #endif int terminate = 0; ip_noise_decide_what_to_do_with_packets_thread_context_t * arbitrator_context; #ifndef __KERNEL__ pthread_t decide_what_to_with_packets_thread; #endif ip_noise_release_packets_thread_context_t * release_packets_context; #ifndef __KERNEL__ pthread_t release_packets_thread; #endif #ifndef __KERNEL__ int check; #endif ip_noise_delayer_t * delayer; ip_noise_arbitrator_data_t * data, * * data_ptr; ip_noise_flags_t flags; ip_noise_arbitrator_iface_t * arb_iface; #ifndef __KERNEL__ pthread_t arb_iface_thread; #endif ip_noise_arbitrator_switcher_t * arb_switcher; #ifndef __KERNEL__ pthread_t arb_switcher_thread; #endif #ifdef __KERNEL__ ip_noise_arbitrator_packet_logic_t * packet_logic; #endif printf("IP-Noise Simulator\n"); printf("Written by Shlomi Fish & Roy Glasberg and supervised by Lavy Libman\n"); printf("The Technion - Israel Institute of Technolgy\n"); printf("(c) 2001\n"); #ifndef __KERNEL__ h = ipq_create_handle(0, PF_INET); if (h == NULL) { die(h); } status = ipq_set_mode(h, IPQ_COPY_PACKET, sizeof(message)); if (status < 0) { die(h); } #endif #ifndef __KERNEL__ packets_to_arbitrate_queue = ip_noise_messages_queue_alloc(); #endif delayer = ip_noise_delayer_alloc( ip_noise_delayer_release_function, #ifndef __KERNEL__ (void *)h #else NULL #endif ); release_packets_context = malloc(sizeof(ip_noise_release_packets_thread_context_t)); release_packets_context->delayer = delayer; release_packets_context->terminate = &terminate; #ifndef __KERNEL__ check = pthread_create( &release_packets_thread, NULL, release_packets_thread_func, (void *)release_packets_context ); if (check != 0) { fprintf(stderr, "Could not create the release packets thread!\n"); exit(-1); } #endif data = ip_noise_arbitrator_data_alloc(); data_ptr = malloc(sizeof(*data_ptr)); *data_ptr = data; flags.reinit_switcher = 1; arb_switcher = ip_noise_arbitrator_switcher_alloc(data_ptr, &flags, &terminate); #ifndef __KERNEL__ check = pthread_create( &arb_switcher_thread, NULL, arb_switcher_thread_func, (void *)arb_switcher ); if (check != 0) { fprintf(stderr, "Could not create the arbitrator switcher thread!\n"); exit(-1); } #endif arb_iface = ip_noise_arbitrator_iface_alloc(data_ptr, arb_switcher, &flags); #ifdef __KERNEL__ /* * We assign arb_iface to iface_ptr so it can later be de-allocated * inside the module ip_queue.c. * * */ *iface_ptr = arb_iface; #endif #ifndef __KERNEL__ check = pthread_create( &arb_iface_thread, NULL, arb_iface_thread_func, (void *)arb_iface ); if (check != 0) { fprintf(stderr, "Could not create the arbitrator interface thread!\n"); exit(-1); } #endif arbitrator_context = malloc(sizeof(ip_noise_decide_what_to_do_with_packets_thread_context_t)); #ifndef __KERNEL__ arbitrator_context->queue = packets_to_arbitrate_queue ; arbitrator_context->h = h; #endif arbitrator_context->terminate = &terminate; arbitrator_context->delayer = delayer; arbitrator_context->data = data_ptr; arbitrator_context->flags = &flags; #ifndef __KERNEL__ check = pthread_create( &decide_what_to_with_packets_thread, NULL, ip_noise_decide_what_to_do_with_packets_thread_func, (void *)arbitrator_context ); if (check != 0) { fprintf(stderr, "Could not create the arbitrator thread!\n"); exit(-1); } #else packet_logic = ip_noise_arbitrator_packet_logic_alloc(data_ptr, &flags); return packet_logic; #endif #ifndef __KERNEL__ do { status = ipq_read(h, message, sizeof(message), 0); if (status < 0) { /* die(h); */ } switch(ipq_message_type(message)) { case NLMSG_ERROR: fprintf( stderr, "Received error message %d\n", ipq_get_msgerr(message) ); break; case IPQM_PACKET: { ip_noise_message_t * msg_with_time; struct timezone tz; #if 0 static int num = 0; #endif msg_with_time = malloc(sizeof(ip_noise_message_t)); /* We are copying the entire buffer, because otherwise we get * errors, since ipq_get_packet still relies on this buffer * for reference */ memcpy(msg_with_time->message, message, sizeof(msg_with_time->message)); msg_with_time->m = ipq_get_packet(msg_with_time->message); gettimeofday(&(msg_with_time->tv), &tz); ip_noise_messages_queue_enqueue( packets_to_arbitrate_queue, msg_with_time ); #if 0 printf("Received a message! (%i)\n", num++); #endif #if 0 status = ipq_set_verdict(h, m->packet_id, NF_ACCEPT, 0, NULL); if (status < 0) { die(h); } #endif break; } default: fprintf(stderr, "Unknown message type!\n"); break; } } while (1); #endif ipq_destroy_handle(h); return 0; }
int main(int argc, const char ** argv) { static u8 buf[LTP_MAX_BUF_SIZE]; struct ipq_handle *h = ipq_create_handle(0, NFPROTO_IPV4); if (!h) { LTP_ERROR_LOG("ipq_create_handle failed\n"); goto error1; } int ret = ipq_set_mode(h, IPQ_COPY_PACKET, LTP_MAX_BUF_SIZE); if (-1 == ret) { LTP_ERROR_LOG("ipq_set_mode failed\n"); goto error2; } register_exit_signal_handler(); while (!g_ltp_daemon_exit) { ret = ipq_read(h, buf, LTP_MAX_BUF_SIZE, 0); if (ret < 0) { LTP_ERROR_LOG("ipq_read failed\n"); goto error2; } ret = ipq_message_type(buf); if (likely(IPQM_PACKET == ret)) { LTP_DEBUG_LOG("Get one packet\n"); ipq_packet_msg_t *pkt = ipq_get_packet(buf); if (likely(pkt)) { if (LTP_OK != ltp_ipq_rcv(pkt)) { // Need not the error handler LTP_ERROR_LOG("ltp_ipq_rcv failed\n"); } ret = ipq_set_verdict(h, pkt->packet_id, NF_DROP, pkt->data_len, pkt->payload); if (-1 == ret) { LTP_ERROR_LOG("ipq_set_verdict failed\n"); goto error2; } } else { LTP_ERROR_LOG("ipq_get_packet failed\n"); goto error2; } } else if (NLMSG_ERROR == ret) { LTP_ERROR_LOG("Recevie error msg(%d)\n", ipq_get_msgerr(buf)); goto error2; } else { LTP_ERROR_LOG("Unknown type\n"); goto error2; } } ipq_destroy_handle(h); return LTP_OK; error2: ipq_destroy_handle(h); h = NULL; error1: return LTP_ERR; }
void packet_send() { ipq_set_verdict(h, ipq_get_packet(my_pkt_head.head->buf)->packet_id, NF_ACCEPT, 0, NULL); printf("%ld packet_id send\n", ipq_get_packet(my_pkt_head.head->buf)->packet_id); dequeue(); }
void *processing(void *t){ packet_ctx *ctx; int status; do{ /********************************************* * process쓰레드 들이 동시에 큐에 달라 붙어서 같은 자료를 처리 할수 있다. * 이 경우 어느 한쪽에서 메시지를 처리하고 메모리를 해제하면 나머지 쪽에서 문제가 생길수 있다. * 그래서 큐에서 하나의 쓰레드에만 값을 넘겨 줘야 한다. **************************************************/ pthread_mutex_lock(&queueLock);/*{{{*/ if(ReadyQueue.currentSize>0){ ctx = safe_dequeue(&ReadyQueue); pthread_mutex_unlock(&queueLock); } else{ pthread_mutex_unlock(&queueLock); continue; } /*}}}*/ //에러 처리 if(ctx==NULL) continue;/*{{{*/ dlog(0,"processing\n"); if (status < 0){ die(ctx->h); } /*}}}*/ switch (ipq_message_type(ctx->buf)) { //에러 처리 case NLMSG_ERROR: dlog(0, "Received error message %d\n", ipq_get_msgerr(ctx->buf)); break; case IPQM_PACKET: { /********************** *초기 변수 설정 * *************************/ ipq_packet_msg_t *m = ipq_get_packet(ctx->buf);/*{{{*/ struct tcphdr *tcp=NULL; struct iphdr *ip=NULL; unsigned char *packet = NULL; unsigned char *tcpPayload=NULL; module_prototype module= NULL; int result=0; GListInfo *moduleList; sin_packet_info *packetInfo = malloc(sizeof(sin_packet_info)); memset(packetInfo,0,sizeof(sin_packet_info)); dump_ipq(m);/*}}}*/ if(m->data_len > sizeof(struct iphdr)){ packet = (unsigned char *)m + sizeof(ipq_packet_msg_t);//sizeof(*m) } ip =(struct iphdr *) packet; if(ip->protocol != 6){ //6 is TCP protocol number ipq_set_verdict(ctx->h,m->packet_id,NF_ACCEPT,0,NULL); } tcp =(struct tcphdr *) packet + sizeof(struct iphdr); dump_ip((struct iphdr *)packet); dump((char *)tcp,240); /*********************************** packetInfo 설정 ***********************************/ if(strcmp(m->outdev_name,"eth0")==0){ packetInfo->direction = C2OUT; }else if(strcmp(m->indev_name,"eth0")==0){ packetInfo->direction = OUT2C; } packetInfo->verdicted = 0; packetInfo->modified=0; packetInfo->action =SIN_ACCEPT; /************************ 분류기 ************************/ /* while(0){ char bound=-1; gpointer n; if(bound==C2O){//만일 패킷이 클라이언트에서 외부로 나가는 경우이면 n = tree_find(&BWList, ip->daddr, NULL); if(n != NULL){ cond *data = (cond *)n; if(data->type==DENY){ if(data->action == CONNECTION_CLOSE){ sessionManager(ctx->h,m->packet_id,CONNECTION_CLOSE); continue;// 다음 패킷 처리 } } if(data->type==ALLOW){ if(data->action == CONNECTION_ALLOW){ sessionManager(ctx->h,m->packet_id,CONNECTION_ALLOW); continue;// 다음 패킷 처리 } } } } } */ /********************** * run modules ************************/ glist_rewind(&ModuleList); while((module=(module_prototype)glist_next(&ModuleList))!=NULL){ result = (*module)(ctx->h,m,(const char*)tcp,240); /********** *허용이 아닌 경우 중단으로 해야 한다. *이유는 ACCEPT이지만 다른 종류의 메시지를 보내야 하는 경우도 있기 때문이다. *다만 이 경우에 어떻게 하는게 좋을지 아직 모르겠다. ***********/ if(result == NF_DROP) break; } /********************* * 위에서 처리 한 결과대로 처리한다. * verdict는 한번만 호출되어야 하는것 같다. ***********************/ /******************** 윈도우 사이즈 조절 *******************/ if(result==NF_ACCEPT && ip->protocol == 6){ uint16_t win; #if __BYTE_ORDER == __LITTLE_ENDIAN win = ntohs(tcp->window); if(win>MAXIMUM_WINDOW_SIZE){ tcp->window =htons(MAXIMUM_WINDOW_SIZE); packetInfo->modified=1; //패킷을 수정 했으니 이것을 verdict 하도록 수정해야한다. } #elif __BYTE_ORDER == __BIG_ENDIAN if(win>MAXIMUM_WINDOW_SIZE) { tcp->window = MAXIMUM_WINDOW_SIZE; packetInfo->modified=1; //패킷을 수정 했으니 이것을 verdict 하도록 수정해야한다. #endif } if( packetInfo->modified == 0){ status = ipq_set_verdict(ctx->h, m->packet_id,result, 0, NULL); }else{ /******************* 패킷 수정됐으니 체크섬 재계산-_- *******************/ status = ipq_set_verdict(ctx->h, m->packet_id,result, 0,NULL); } if (status < 0) die(ctx->h); break; } default: fprintf(stderr, "Unknown message type!\n"); break; } } while (1); ipq_destroy_handle(ctx->h); return 0; }
static int ipq_daq_acquire ( void* handle, int cnt, DAQ_Analysis_Func_t callback, void* user) { IpqImpl* impl = (IpqImpl*)handle; int n = 0; DAQ_PktHdr_t hdr; // If cnt is <= 0, don't limit the packets acquired. However, // impl->count = 0 has a special meaning, so interpret accordingly. impl->count = (cnt == 0) ? -1 : cnt; hdr.device_index = 0; hdr.flags = 0; while ( impl->count < 0 || n < impl->count ) { int ipqt, status = ipq_read( impl->ipqh, impl->buf, MSG_BUF_SIZE, impl->timeout); if ( status <= 0 ) { if ( status < 0 ) { DPE(impl->error, "%s: ipq_read=%d error %s", __FUNCTION__, status, ipq_errstr()); return DAQ_ERROR; } return 0; } ipqt = ipq_message_type(impl->buf); if ( ipqt == IPQM_PACKET ) { DAQ_Verdict verdict; ipq_packet_msg_t* ipqm = ipq_get_packet(impl->buf); SetPktHdr(impl, ipqm, &hdr); impl->stats.hw_packets_received++; if ( impl->fcode.bf_insns && sfbpf_filter(impl->fcode.bf_insns, ipqm->payload, hdr.caplen, hdr.caplen) == 0 ) { verdict = DAQ_VERDICT_PASS; impl->stats.packets_filtered++; } else { verdict = callback(user, &hdr, (uint8_t*)ipqm->payload); impl->stats.verdicts[verdict]++; impl->stats.packets_received++; } if ( impl->passive ) verdict = DAQ_VERDICT_PASS; switch ( verdict ) { case DAQ_VERDICT_BLOCK: case DAQ_VERDICT_BLACKLIST: status = ipq_set_verdict( impl->ipqh, ipqm->packet_id, NF_DROP, 0, NULL); break; case DAQ_VERDICT_REPLACE: status = ipq_set_verdict( impl->ipqh, ipqm->packet_id, NF_ACCEPT, hdr.pktlen, ipqm->payload); break; case DAQ_VERDICT_PASS: case DAQ_VERDICT_WHITELIST: case DAQ_VERDICT_IGNORE: default: status = ipq_set_verdict( impl->ipqh, ipqm->packet_id, NF_ACCEPT, 0, NULL); break; } if ( status < 0 ) { DPE(impl->error, "%s: ipq_set_verdict=%d error %s", __FUNCTION__, status, ipq_errstr()); return DAQ_ERROR; } n++; } else { // NLMSG_ERROR is supposed to be the only other valid type status = ipq_get_msgerr(impl->buf); DPE(impl->error, "%s: ipq_message_type=%d error=%d %s", __FUNCTION__, ipqt, status, ipq_errstr()); // ipq_message_type=2 error=1 Timeout // keep looping upon timeout or other errors } } return 0; }
int main(int argc, char **argv) { int verdict; unsigned char buf[BUFSIZE]; struct ipq_handle *h; int cfd; int daemonize = 1; if (argc > 1) { if (!strcmp(argv[1], "-nd")) { daemonize = 0; } } srand(0); cfd = make_ipc(); if ( cfd < 0 ) exit(1); printhelp(); h = make_ipq(); if (daemonize) { FILE *logfile = 0; int pid; logfile = fopen(LOGFILE, "a"); if (!logfile) { perror("Failed to open " LOGFILE); exit(1); } if ( daemon(0, 0) < 0 ) { perror("Failed to daemonize"); exit(1); } if ( dup2(fileno(logfile), STDERR_FILENO) < 0 ) abort(); fclose(logfile); pid = writepid(); if (pid < 0) return -1; /* disable low water mark check for io pages */ if (setpriority(PRIO_PROCESS, pid, PRIO_SPECIAL_IO)) { perror("Unable to prioritize tapdisk proc"); exit(1); } TRACE("Start pfilter PID %d\n", pid); } do { ssize_t status; int type; status = ipq_read(h, buf, BUFSIZE, 0); if (status < 0) fail_retry(&h); type = ipq_message_type(buf); switch (type) { case NLMSG_ERROR: TRACE("pfilter: Received error message %d\n", ipq_get_msgerr(buf)); break; case IPQM_PACKET: { ipq_packet_msg_t *m = ipq_get_packet(buf); verdict = filter(); status = ipq_set_verdict(h, m->packet_id, verdict, 0, NULL); if (status < 0) fail_retry(&h); trace_data(verdict); break; } default: TRACE("pfilter: Unknown message type: %d\n", type); break; } } while (1); ipq_destroy_handle(h); return 0; }
// This is the main entry point in to the control code // and will be run in it's own thread void *ControlRun(void *pParam){ struct sockaddr_in FromAddr; socklen_t SockaddrLen; struct timeval NowTime; BYTE PacketBuffer[max(sizeof(MASTERPACKET), sizeof(CLIENTPACKET)) + 2]; int PacketSize, i, j; //pthread_t idWriteStatsFileThread; // Clear stats memset(&ClientStats, 0, sizeof(ClientStats)); // Open UDP connection to server memset(&MasterAddr, 0, sizeof(MasterAddr)); MasterAddr.sin_family = AF_INET; MasterAddr.sin_addr.s_addr = inet_addr(Config.MasterIp); MasterAddr.sin_port = htons(Config.MasterPort); hControlPort = socket(PF_INET, SOCK_DGRAM, 0); if(hControlPort < 0){ Log(LOG_ERR, "Failed to open client socket"); return NULL; } // Bind it to a local port memset(&LocalAddr, 0, sizeof(LocalAddr)); LocalAddr.sin_family = AF_INET; LocalAddr.sin_addr.s_addr = inet_addr("0.0.0.0"); LocalAddr.sin_port = htons(0); if(bind(hControlPort, (struct sockaddr *)&LocalAddr, sizeof(LocalAddr)) != 0){ close(hControlPort); Log(LOG_ERR, "Failed to bind to client port"); return NULL; } // Get initial wireless data GetWirelessState(); // Store intial background processing time gettimeofday(&LastCtrlBackgroundTime, NULL); LastCtrlBackgroundTime.tv_sec -= 8; // Set the initial status ClientStatus = CS_REGISTER; // Send register packet SendRegisterPacket(); // Set an initial last Rx time gettimeofday(&LastRxActivityTime, NULL); // Setup cleanup function (closes the port) pthread_cleanup_push((void*)ControlCleanup, NULL); // While we should run (helps exit a thread cleanly) while(!ExitControlThread){ struct timeval Timeout; fd_set readfds; int SelRet; FD_ZERO(&readfds); FD_SET(hControlPort, &readfds); // Wait 2 sec for UDP data Timeout.tv_sec = 2; Timeout.tv_usec = 0; SelRet = select(hControlPort+1, &readfds, NULL, NULL, &Timeout); // Error in select if(SelRet < 0){ // Select error Log(LOG_ERR, "Error waiting for master packet"); } // Data pending else if(SelRet > 0){ // Get packet from master SockaddrLen = sizeof(FromAddr); PacketSize = recvfrom(hControlPort, PacketBuffer, sizeof(PacketBuffer), 0, (struct sockaddr *)&FromAddr, &SockaddrLen); // Check packet size if(PacketSize != sizeof(MASTERPACKET) + 2){ // Wrong sized packet Log(LOG_ERR, "Client got packet of incorrect size"); } else{ // Check the checksum for(i = 0, j = 0; i < sizeof(MASTERPACKET); i++){ j <<= 8; j += PacketBuffer[i]; } if(PacketBuffer[i] != (USHORT)j){ // Corrupted packet Log(LOG_ERR, "Client got corrupted packet"); } else{ int Packets, Bytes, Queue, k; if(ClientStatus != CS_CONNECTED) Log(LOG_INFO, "Client registered"); // Update the status and last activity time ClientStatus = CS_CONNECTED; gettimeofday(&LastRxActivityTime, NULL); // Incriment poll count ClientStats.Polls++; // Send Packets up to allowed amount SendPackets(((MASTERPACKET*)PacketBuffer)->MaxPacketsToSend, ((MASTERPACKET*)PacketBuffer)->MaxBytesToSend); // Wait for access to the packet queue pthread_mutex_lock(&PacketQueueMutex); // Work out packets/bytes left in queues Packets = 0; Bytes = 0; for(Queue = 0; Queue < PacketQueues; Queue++){ k = PacketQueueTail[Queue]; while(PacketQueueHead[Queue] != k){ Packets++; Bytes += ((ipq_packet_msg_t *)&PacketQueue[Queue][k * sizeof(struct ipq_packet_msg)])->data_len; k++; if(k >= Config.Queue) k = 0; } } // Release access to the packet queue pthread_mutex_unlock(&PacketQueueMutex); // Send 'done' packet memset(PacketBuffer, 0, sizeof(PacketBuffer)); ((CLIENTPACKET*)PacketBuffer)->TypeId = CLIENTID_END; ((CLIENTPACKET*)PacketBuffer)->Rate = CurrentRate; ((CLIENTPACKET*)PacketBuffer)->Signal = CurrentSignal; ((CLIENTPACKET*)PacketBuffer)->Noise = CurrentNoise; ((CLIENTPACKET*)PacketBuffer)->PacketsInQueue = Packets; ((CLIENTPACKET*)PacketBuffer)->BytesInQueue = Bytes; for(i = 0, j = 0; i < sizeof(CLIENTPACKET); i++){ j <<= 8; j += PacketBuffer[i]; } PacketBuffer[i] = (USHORT)j; sendto(hControlPort, &PacketBuffer, sizeof(CLIENTPACKET)+2, 0, (struct sockaddr *)&MasterAddr, sizeof(MasterAddr)); // Update the last activity time gettimeofday(&LastTxActivityTime, NULL); } } } // Do background processing here, this should run at least every 2 sec // Get current time gettimeofday(&NowTime, NULL); // If no Tx or Rx recently if(NowTime.tv_sec > LastRxActivityTime.tv_sec + SERVERREREGISTER && NowTime.tv_sec > LastTxActivityTime.tv_sec + SERVERREREGISTER){ // Reregister SendRegisterPacket(); } // If no Rx for ages if(NowTime.tv_sec > LastRxActivityTime.tv_sec + SERVERTIMEOUT && ClientStatus != CS_NOSERVER){ Log(LOG_INFO, "Client lost master connection"); // Wait for access to the packet queue pthread_mutex_lock(&PacketQueueMutex); for(i = 0; i < PacketQueues; i++){ // Send any/all packets in queue while(PacketQueueHead[i] != PacketQueueTail[i]){ // Send the packet ipq_set_verdict(hIpq, ((ipq_packet_msg_t *)&PacketQueue[i][PacketQueueTail[i] * sizeof(struct ipq_packet_msg)])->packet_id, NF_ACCEPT, 0, NULL); PacketQueueTail[i]++; if(PacketQueueTail[i] >= Config.Queue) PacketQueueTail[i] = 0; } } // Release access to the packet queue pthread_mutex_unlock(&PacketQueueMutex); // Update the status to allow packets straight through ClientStatus = CS_NOSERVER; } // If no background processing for 10 sec (approx.) if(NowTime.tv_sec >= LastCtrlBackgroundTime.tv_sec + 10){ // Update wireless data GetWirelessState(); // Store intial background processing time gettimeofday(&LastCtrlBackgroundTime, NULL); if(Config.StatsFilename[0] != 0x00){ // Start file write function in own threa //idWriteStatsFileThread = 0; //pthread_create(&idWriteStatsFileThread, NULL, &WriteStatsFile, NULL); // TODO: Figure out why doing it in a thread dies sooner or later (no further updates) WriteStatsFile(NULL); } //Reset poll count ClientStats.Polls = 0; } } // Call and clear cleanup function pthread_cleanup_pop(1); return NULL; }
int main(int argc, char **argv) { int status, i; unsigned int payload_len, payload_offset; unsigned char buf[BUFSIZE], listtype[8]; struct ipq_handle *h; unsigned char *match, *folder, *url; PURL current; strcpy (listtype, argv[1]); get_url_info(); h = ipq_create_handle(0, PF_INET); if (!h) { die(h); } status = ipq_set_mode(h, IPQ_COPY_PACKET, BUFSIZE); if (status < 0) { die(h); } do { memset(buf, 0, sizeof(buf)); status = ipq_read(h, buf, BUFSIZE, 0); if (status < 0) { die(h); } switch (ipq_message_type(buf)) { case NLMSG_ERROR: { fprintf(stderr, "Received error message %d\n", ipq_get_msgerr(buf)); break; } case IPQM_PACKET: { ipq_packet_msg_t *m = ipq_get_packet(buf); char decision = 'n'; struct iphdr *iph = ((struct iphdr *)m->payload); struct tcphdr *tcp = (struct tcphdr *)(m->payload + (iph->ihl<<2)); match = folder = url = NULL; payload_offset = ((iph->ihl)<<2) + (tcp->doff<<2); payload_len = (unsigned int)ntohs(iph->tot_len) - ((iph->ihl)<<2) + (tcp->doff<<2); match = (char *)(m->payload + payload_offset); if(strstr(match, "GET ") == NULL && strstr(match, "POST ") == NULL && strstr(match, "HEAD ") == NULL) { status = ipq_set_verdict(h, m->packet_id, NF_ACCEPT, 0, NULL); //printf("****NO HTTP INFORMATION!!!\n"); if (status < 0) { die(h); } break; } for (current = purl; current != NULL; current = current->next) { if (current->folder[0] != '\0') { folder = strstr(match, current->folder); } //printf("####payload = %s\n\n", match); if ( (url = strstr(match, current->website)) != NULL ) { if (strcmp(listtype, "Exclude") == 0) { if ( (folder != NULL) || (current->folder[0] == '\0') ) { status = ipq_set_verdict(h, m->packet_id, NF_DROP, 0, NULL); //printf("####This page is blocked by Exclude list!"); decision = 'y'; } else { status = ipq_set_verdict(h, m->packet_id, NF_ACCEPT, 0, NULL); //printf("###Website hits but folder no hit in Exclude list! packets pass\n"); decision = 'y'; } if (status < 0) { die(h); } break; } else { if ( (folder != NULL) || (current->folder[0] == '\0') ) { status = ipq_set_verdict(h, m->packet_id, NF_ACCEPT, 0, NULL); //printf("####This page is accepted by Include list!"); decision = 'y'; } else { status = ipq_set_verdict(h, m->packet_id, NF_DROP, 0, NULL); //printf("####Website hits but folder no hit in Include list!, packets drop\n"); decision = 'y'; } if (status < 0) { die(h); } break; } } } if (url == NULL) { if (strcmp(listtype, "Exclude") == 0) { status = ipq_set_verdict(h, m->packet_id, NF_ACCEPT, 0, NULL); //printf("~~~~No Url hits!! This page is accepted by Exclude list!\n"); decision = 'y'; } else { status = ipq_set_verdict(h, m->packet_id, NF_DROP, 0, NULL); //printf("~~~~No Url hits!! This page is blocked by Include list!\n"); decision = 'y'; } if (status < 0) { die(h); } } if (decision == 'n') { ipq_set_verdict(h, m->packet_id, NF_ACCEPT, 0, NULL); //printf("~~~None of rules can be applied!! Traffic is allowed!!\n"); } break; } default: { fprintf(stderr, "Unknown message type!\n"); break; } } } while (1); ipq_destroy_handle(h); return 0; }
static void packet_input(int fd) #endif { rt_table_t *fwd_rt, *rev_rt, *repair_rt, *next_hop_rt; u_int32_t dest_addr, src_addr; u_int8_t rreq_flags = 0; unsigned int ifindex; struct ip_data *ipd = NULL; #ifdef NS_PORT ifindex = NS_IFINDEX; // Always use ns interface fwd_rt = NULL; // In case of broadcast we provide no next hop ipd = NULL; // No ICMP messaging struct hdr_cmn *ch = HDR_CMN(p); struct hdr_ip *ih = HDR_IP(p); src_addr = ih->saddr(); dest_addr = ih->daddr(); /* Any packets with our IP address as destination arriving here are packets that weren't caught by any agent attached to the node. Throw away those. */ if (dest_addr == DEV_IFINDEX(ifindex).ipaddr) { DEBUG(LOG_WARNING, 0, "processPacket: Received orphan packet. Throwing it away."); Packet::free(p); return; } /* If this is a TCP packet and we don't have a route, we should set the gratuituos flag in the RREQ. */ if (ch->ptype() == PT_TCP) { rreq_flags |= RREQ_GRATUITOUS; } #else int status; char buf[BUFSIZE], *dev_name; ipq_packet_msg_t *pkt; struct iphdr *ip; struct udphdr *udp; struct icmphdr *icmp = NULL; ipq_read(h, buf, BUFSIZE, 0); status = ipq_message_type(buf); if (status == NLMSG_ERROR) { fprintf(stderr, "ERROR packet_input: Check that the ip_queue.o module is loaded.\n"); die(h); } pkt = ipq_get_packet(buf); #ifdef DEBUG_PACKET DEBUG(LOG_DEBUG, 0, "Protocol %u indev=%s outdev=%s\n", pkt->hw_protocol, pkt->indev_name, pkt->outdev_name); #endif if (pkt->hook == 0) dev_name = pkt->indev_name; else if (pkt->hook == 3) dev_name = pkt->outdev_name; else dev_name = NULL; /* We know from kaodv.c that this is an IP packet */ ip = (struct iphdr *) pkt->payload; dest_addr = ntohl(ip->daddr); src_addr = ntohl(ip->saddr); switch (ip->protocol) { /* Don't process AODV control packets (UDP on port 654). They are accounted for on the aodv socket */ case IPPROTO_UDP: udp = (struct udphdr *) ((char *) ip + (ip->ihl << 2)); if (ntohs(udp->dest) == AODV_PORT || ntohs(udp->source) == AODV_PORT) goto accept; break; /* If this is a TCP packet and we don't have a route, we should set the gratuituos flag in the RREQ. */ case IPPROTO_TCP: rreq_flags |= RREQ_GRATUITOUS; break; /* We set the gratuitous flag also on ICMP ECHO requests, since the destination will also need a route back for the reply... */ case IPPROTO_ICMP: icmp = (struct icmphdr *) ((char *) ip + (ip->ihl << 2)); if (icmp->type == ICMP_ECHO) rreq_flags |= RREQ_GRATUITOUS; #ifdef DEBUG_PACKET DEBUG(LOG_INFO, 0, "packet_input: setting G flag for RREQ to %s", ip_to_str(dest_addr)); #endif break; default: } #ifdef DEBUG_PACKET DEBUG(LOG_INFO, 0, "packet_input: pkt to %s", ip_to_str(dest_addr)); #endif if (dev_name) ifindex = if_nametoindex(dev_name); else ifindex = 0; #endif /* NS_PORT */ /* If the packet is not interesting we just let it go through... */ if ((dest_addr == AODV_BROADCAST) || (dest_addr == DEV_IFINDEX(ifindex).ipaddr) || (dest_addr == DEV_IFINDEX(ifindex).broadcast) || ((internet_gw_mode && this_host.gateway_mode) && ((dest_addr & DEV_IFINDEX(ifindex).netmask) != DEV_IFINDEX(ifindex).broadcast))) goto accept; /* Find the entry of the neighboring node and the destination (if any). */ rev_rt = rt_table_find_active(src_addr); fwd_rt = rt_table_find_active(dest_addr); /* If a packet is received on the NF_IP_PRE_ROUTING hook, i.e. inbound on the interface and we don't have a route to the destination, we should send an RERR to the source and then drop the package... */ /* NF_IP_PRE_ROUTING = 0 */ #ifdef NS_PORT #define PACKET_IS_INBOUND ch->direction() == hdr_cmn::UP #else #define PACKET_IS_INBOUND pkt->hook == 0 #endif if ((dest_addr != DEV_IFINDEX(ifindex).ipaddr) && (!fwd_rt && PACKET_IS_INBOUND)) { rt_table_t *rt_entry; u_int32_t rerr_dest; RERR *rerr; DEBUG(LOG_DEBUG, 0, "packet_input: Sending RERR for unknown dest %s", ip_to_str(dest_addr)); /* There is an expired entry in the routing table we want to send along the seqno in the RERR... */ rt_entry = rt_table_find(dest_addr); if (rt_entry) { rerr = rerr_create(0, rt_entry->dest_addr, rt_entry->dest_seqno); rt_table_update_timeout(rt_entry, DELETE_PERIOD); } else rerr = rerr_create(0, dest_addr, 0); /* Unicast the RERR to the source of the data transmission if * possible, otherwise we broadcast it. */ if (rev_rt) rerr_dest = rev_rt->next_hop; else rerr_dest = AODV_BROADCAST; aodv_socket_send((AODV_msg *) rerr, rerr_dest, RERR_CALC_SIZE(rerr), 1, &DEV_IFINDEX(ifindex)); if (wait_on_reboot) { DEBUG(LOG_DEBUG, 0, "packet_input: Wait on reboot timer reset."); timer_add_msec(&worb_timer, DELETE_PERIOD); } #ifdef NS_PORT drop(p, DROP_RTR_NO_ROUTE); #else status = ipq_set_verdict(h, pkt->packet_id, NF_DROP, 0, NULL); if (status < 0) die(h); #endif return; } /* Check if the route is currently in repair. In that case just buffer the packet */ repair_rt = rt_table_find(dest_addr); if (repair_rt && (repair_rt->flags & LREPAIR)) { #ifdef NS_PORT packet_queue_add(p, dest_addr); #else packet_queue_add(pkt->packet_id, dest_addr); #endif return; } /* update_timers: */ /* When forwarding a packet, we update the lifetime of the destination's routing table entry, as well as the entry for the next hop neighbor (if not the same). AODV draft 10, section 6.2. */ if (fwd_rt && dest_addr != DEV_IFINDEX(ifindex).ipaddr) { rt_table_update_timeout(fwd_rt, ACTIVE_ROUTE_TIMEOUT); next_hop_rt = rt_table_find_active(fwd_rt->next_hop); if (next_hop_rt && next_hop_rt->dest_addr != fwd_rt->dest_addr) rt_table_update_timeout(next_hop_rt, ACTIVE_ROUTE_TIMEOUT); } /* Also update the reverse route and reverse next hop along the path back, since routes between originators and the destination are expected to be symmetric. */ if (rev_rt) { rt_table_update_timeout(rev_rt, ACTIVE_ROUTE_TIMEOUT); next_hop_rt = rt_table_find_active(rev_rt->next_hop); if (next_hop_rt && next_hop_rt->dest_addr != fwd_rt->dest_addr) rt_table_update_timeout(next_hop_rt, ACTIVE_ROUTE_TIMEOUT); } #ifdef DEBUG_PACKET DEBUG(LOG_INFO, 0, "packet_input: d=%s s=%s", ip_to_str(dest_addr), ip_to_str(src_addr)); #endif /* DEBUG_PACKET */ if (!fwd_rt || (fwd_rt->hcnt == 1 && (fwd_rt->flags & UNIDIR))) { /* Buffer packets... Packets are queued by the ip_queue_aodv.o module already. We only need to save the handle id, and return the proper verdict when we know what to do... */ #ifdef NS_PORT packet_queue_add(p, dest_addr); #else packet_queue_add(pkt->packet_id, dest_addr); /* If the request is generated locally by an application, we save the IP header + 64 bits of data for sending an ICMP Destination Host Unreachable in case we don't find a route... */ if (src_addr == DEV_IFINDEX(ifindex).ipaddr) { ipd = (struct ip_data *) malloc(sizeof(struct ip_data)); if (ipd < 0) { perror("Malloc for IP data failed!"); exit(-1); } ipd->len = (ip->ihl << 2) + 8; /* IP header + 64 bits data (8 bytes) */ memcpy(ipd->data, ip, ipd->len); } else ipd = NULL; #endif rreq_route_discovery(dest_addr, rreq_flags, ipd); return; } accept: #ifdef NS_PORT if (fwd_rt) sendPacket(p, fwd_rt->next_hop, 0.0); else drop(p, DROP_RTR_NO_ROUTE); #else status = ipq_set_verdict(h, pkt->packet_id, NF_ACCEPT, 0, NULL); if (status < 0) die(h); #endif return; }
// This is called when a packet message is received int ProcessPacketMessage(ipq_packet_msg_t *pPacketMsg){ struct timeval NowTime; int Queue; // If we're acting as a client if(Config.Flags & CONFIGFLAGS_CLIENT){ // If we don't have a server connection if(ClientStatus == CS_NOSERVER){ // Just let the packet straight through (fail safe) ipq_set_verdict(hIpq, pPacketMsg->packet_id, NF_ACCEPT, 0, NULL); return 1; } } // If we're acting as a self client if(Config.Flags & CONFIGFLAGS_SELFCLIENT){ // If we don't have any clients if(ClientCount == 0){ // Just let the packet straight through (fail safe) ipq_set_verdict(hIpq, pPacketMsg->packet_id, NF_ACCEPT, 0, NULL); return 1; } } // Note: The timestamp_sec value in struct ipq_packet_msg always appears to be 0, // so we will insert our own time stamp for when we got it (not as good, but oh well). // Get current time gettimeofday(&NowTime, NULL); pPacketMsg->timestamp_sec = NowTime.tv_sec; pPacketMsg->timestamp_usec = NowTime.tv_usec; // Workout queue that packet should go in Queue = PacketPriority(pPacketMsg); // Wait for access to the packet queue pthread_mutex_lock(&PacketQueueMutex); // Store packet meta data (including payload size, but not payload // itself!) at the head of the queue memcpy(&PacketQueue[Queue][PacketQueueHead[Queue] * sizeof(struct ipq_packet_msg)], pPacketMsg, sizeof(struct ipq_packet_msg)); // Move the head offset PacketQueueHead[Queue]++; if(PacketQueueHead[Queue] >= Config.Queue) PacketQueueHead[Queue] = 0; // If we just looped around if(PacketQueueHead[Queue] == PacketQueueTail[Queue]){ // Drop the oldest (overwritten) packet ipq_set_verdict(hIpq, ((ipq_packet_msg_t *)&PacketQueue[Queue][PacketQueueTail[Queue] * sizeof(struct ipq_packet_msg)])->packet_id, NF_DROP, 0, NULL); // Move the Tail offset PacketQueueTail[Queue]++; if(PacketQueueTail[Queue] >= Config.Queue) PacketQueueTail[Queue] = 0; } // Release access to the packet queue pthread_mutex_unlock(&PacketQueueMutex); return 1; }
int main(int argc, char **argv) { int status; unsigned char buf[BUFSIZE]; struct ipq_handle *h; struct iphdr *iphead; h = ipq_create_handle(0, PF_INET); if (!h) die(h); status = ipq_set_mode(h, IPQ_COPY_PACKET, BUFSIZE); if (status < 0) die(h); do{ status = ipq_read(h, buf, BUFSIZE, 0); if (status < 0) die(h); switch (ipq_message_type(buf)) { case NLMSG_ERROR: fprintf(stderr, "Received error message %d\\n", ipq_get_msgerr(buf)); break; case IPQM_PACKET: { ipq_packet_msg_t *m = ipq_get_packet(buf); char *dest = NULL; struct in_addr daddr; iphead = (struct iphdr *)m->payload; if(iphead->daddr == inet_addr(TO)) { status = ipq_set_verdict(h,m->packet_id, NF_ACCEPT,0,NULL); if(status < 0) die(h); break; } else { status = ipq_set_verdict(h,m->packet_id, NF_DROP,0,NULL); if(status < 0) die(h); break; } // status = ipq_set_verdict(h, m->packet_id, // NF_ACCEPT, 0, NULL); // if (status < 0) // die(h); // break; } default: fprintf(stderr, "Unknown message type!\\n"); break; } } while (1); ipq_destroy_handle(h); return 0; }
static void packet_input(int fd) #endif { rt_table_t *fwd_rt, *rev_rt, *next_hop_rt = NULL; struct in_addr dest_addr, src_addr; u_int8_t rreq_flags = 0; unsigned int ifindex; struct ip_data *ipd = NULL; int pkt_flags = 0; #ifdef NS_PORT ifindex = NS_IFINDEX; /* Always use ns interface */ fwd_rt = NULL; /* For broadcast we provide no next hop */ ipd = NULL; /* No ICMP messaging */ struct hdr_cmn *ch = HDR_CMN(p); struct hdr_ip *ih = HDR_IP(p); src_addr.s_addr = ih->saddr(); dest_addr.s_addr = ih->daddr(); /* If this is a TCP packet and we don't have a route, we should set the gratuituos flag in the RREQ. */ if (ch->ptype() == PT_TCP) { rreq_flags |= RREQ_GRATUITOUS; } #else int status; char buf[sizeof(struct nlmsghdr)+sizeof(ipq_packet_msg_t)+BUFSIZE]; char *dev_name; ipq_packet_msg_t *pkt; struct iphdr *ip; struct udphdr *udp; struct icmphdr *icmp = NULL; status = ipq_read(h, buf, sizeof(buf), -1); if (status < 0) { DEBUG(LOG_DEBUG, 0, "%s", ipq_errstr()); ipq_perror(NULL); return; } if (ipq_message_type(buf) == NLMSG_ERROR) { fprintf(stderr, "ERROR packet_input: Check that the ip_queue.o module is loaded.\n"); die(h); } pkt = ipq_get_packet(buf); #ifdef DEBUG_PACKET DEBUG(LOG_DEBUG, 0, "Protocol %u indev=%s outdev=%s\n", pkt->hw_protocol, pkt->indev_name, pkt->outdev_name); #endif if (pkt->hook == 0) dev_name = pkt->indev_name; else if (pkt->hook == 3) dev_name = pkt->outdev_name; else dev_name = NULL; /* We know from kaodv.c that this is an IP packet */ ip = (struct iphdr *) pkt->payload; dest_addr.s_addr = ip->daddr; src_addr.s_addr = ip->saddr; switch (ip->protocol) { /* Don't process AODV control packets (UDP on port 654). They are accounted for on the aodv socket */ case IPPROTO_UDP: udp = (struct udphdr *) ((char *) ip + (ip->ihl << 2)); if (ntohs(udp->dest) == AODV_PORT || ntohs(udp->source) == AODV_PORT) goto accept; break; /* If this is a TCP packet and we don't have a route, we should set the gratuituos flag in the RREQ. */ case IPPROTO_TCP: rreq_flags |= RREQ_GRATUITOUS; break; /* We set the gratuitous flag also on ICMP ECHO requests, since the destination will also need a route back for the reply... */ case IPPROTO_ICMP: icmp = (struct icmphdr *) ((char *) ip + (ip->ihl << 2)); if (icmp->type == ICMP_ECHO) rreq_flags |= RREQ_GRATUITOUS; #ifdef DEBUG_PACKET DEBUG(LOG_INFO, 0, "setting G flag for RREQ to %s", ip_to_str(dest_addr)); #endif break; #ifdef CONFIG_GATEWAY case IPPROTO_MIPE: if (internet_gw_mode) { ip = ip_pkt_decapsulate(ip); if (ip == NULL) { DEBUG(LOG_ERR, 0, "Decapsulation failed..."); exit(-1); } pkt_flags |= PKT_DEC; } break; #endif /* CONFIG_GATEWAY */ } #ifdef DEBUG_PACKET DEBUG(LOG_INFO, 0, "pkt to %s", ip_to_str(dest_addr)); #endif if (dev_name) { ifindex = name2index(dev_name); if (ifindex < 0) { DEBUG(LOG_ERR, 0, "name2index error!"); return; } } else ifindex = 0; #endif /* NS_PORT */ /* If the packet is not interesting we just let it go through... */ if (dest_addr.s_addr == AODV_BROADCAST || dest_addr.s_addr == DEV_IFINDEX(ifindex).broadcast.s_addr) { #ifdef NS_PORT /* Limit Non AODV broadcast packets (Rolf Winter * <[email protected]). */ ih->ttl() = ih->ttl() - 1; if(ih->ttl() < 1) Packet::free(p); else sendPacket(p, dest_addr, 0.0); return; #else goto accept; #endif } /* Find the entry of the neighboring node and the destination (if any). */ rev_rt = rt_table_find(src_addr); fwd_rt = rt_table_find(dest_addr); #ifdef CONFIG_GATEWAY /* Check if we have a route and it is an Internet destination (Should be * encapsulated and routed through the gateway). */ if (fwd_rt && (fwd_rt->state == VALID) && (fwd_rt->flags & RT_INET_DEST)) { /* The destination should be relayed through the IG */ rt_table_update_timeout(fwd_rt, ACTIVE_ROUTE_TIMEOUT); #ifdef NS_PORT p = pkt_encapsulate(p, fwd_rt->next_hop); if (p == NULL) { DEBUG(LOG_ERR, 0, "IP Encapsulation failed!"); return; } /* Update pointers to headers */ ch = HDR_CMN(p); ih = HDR_IP(p); #else ip = ip_pkt_encapsulate(ip, fwd_rt->next_hop, BUFSIZE); if (ip == NULL) { DEBUG(LOG_ERR, 0, "Minimal IP Encapsulation failed!"); exit(-1); } #endif dest_addr = fwd_rt->next_hop; fwd_rt = rt_table_find(dest_addr); pkt_flags |= PKT_ENC; } #endif /* CONFIG_GATEWAY */ /* UPDATE TIMERS on active forward and reverse routes... */ /* When forwarding a packet, we update the lifetime of the destination's routing table entry, as well as the entry for the next hop neighbor (if not the same). AODV draft 10, section 6.2. */ if (fwd_rt && fwd_rt->state == VALID && dest_addr.s_addr != DEV_IFINDEX(ifindex).ipaddr.s_addr) { rt_table_update_timeout(fwd_rt, ACTIVE_ROUTE_TIMEOUT); next_hop_rt = rt_table_find(fwd_rt->next_hop); if (next_hop_rt && next_hop_rt->state == VALID && next_hop_rt->dest_addr.s_addr != fwd_rt->dest_addr.s_addr) rt_table_update_timeout(next_hop_rt, ACTIVE_ROUTE_TIMEOUT); } /* Also update the reverse route and reverse next hop along the path back, since routes between originators and the destination are expected to be symmetric. */ if (rev_rt && rev_rt->state == VALID) { rt_table_update_timeout(rev_rt, ACTIVE_ROUTE_TIMEOUT); next_hop_rt = rt_table_find(rev_rt->next_hop); if (next_hop_rt && next_hop_rt->state == VALID && rev_rt && next_hop_rt->dest_addr.s_addr != rev_rt->dest_addr.s_addr) rt_table_update_timeout(next_hop_rt, ACTIVE_ROUTE_TIMEOUT); /* Update HELLO timer of next hop neighbor if active */ if (!llfeedback && next_hop_rt->hello_timer.used) { struct timeval now; gettimeofday(&now, NULL); hello_update_timeout(next_hop_rt, &now, ALLOWED_HELLO_LOSS * HELLO_INTERVAL); } } /* OK, the timeouts have been updated. Now see if either: 1. The packet is for this node -> ACCEPT. 2. The packet is not for this node -> Send RERR (someone want's this node to forward packets although there is no route) or Send RREQ. */ /* If the packet is destined for this node, then just accept it. */ if (memcmp(&dest_addr, &DEV_IFINDEX(ifindex).ipaddr, sizeof(struct in_addr)) == 0) { #ifdef NS_PORT ch->size() -= IP_HDR_LEN; // cut off IP header size 4/7/99 -dam target_->recv(p, (Handler*)0); p = 0; return; #else goto accept; #endif } if (!fwd_rt || fwd_rt->state == INVALID || (fwd_rt->hcnt == 1 && (fwd_rt->flags & RT_UNIDIR))) { /* Check if the route is marked for repair or is INVALID. In * that case, do a route discovery. */ if (fwd_rt && (fwd_rt->flags & RT_REPAIR)) goto route_discovery; /* If a packet is received on the NF_IP_PRE_ROUTING hook, i.e. inbound on the interface and we don't have a route to the destination, we should send an RERR to the source and then drop the package... */ /* NF_IP_PRE_ROUTING = 0 */ #ifdef NS_PORT #define PACKET_IS_INBOUND ch->direction() == hdr_cmn::UP #else #define PACKET_IS_INBOUND pkt->hook == 0 #endif if (PACKET_IS_INBOUND) { struct in_addr rerr_dest; RERR *rerr; #ifdef NS_PORT struct in_addr nh; nh.s_addr = ch->prev_hop_; DEBUG(LOG_DEBUG, 0, "No route, src=%s dest=%s prev_hop=%s - DROPPING!", ip_to_str(src_addr), ip_to_str(dest_addr), ip_to_str(nh)); #endif if (fwd_rt) { rerr = rerr_create(0, fwd_rt->dest_addr, fwd_rt->dest_seqno); rt_table_update_timeout(fwd_rt, DELETE_PERIOD); } else rerr = rerr_create(0, dest_addr, 0); DEBUG(LOG_DEBUG, 0, "Sending RERR to prev hop %s for unknown dest %s", ip_to_str(src_addr), ip_to_str(dest_addr)); /* Unicast the RERR to the source of the data transmission * if possible, otherwise we broadcast it. */ if (rev_rt && rev_rt->state == VALID) rerr_dest = rev_rt->next_hop; else rerr_dest.s_addr = AODV_BROADCAST; aodv_socket_send((AODV_msg *) rerr, rerr_dest, RERR_CALC_SIZE(rerr), 1, &DEV_IFINDEX(ifindex)); if (wait_on_reboot) { DEBUG(LOG_DEBUG, 0, "Wait on reboot timer reset."); timer_set_timeout(&worb_timer, DELETE_PERIOD); } #ifdef NS_PORT /* DEBUG(LOG_DEBUG, 0, "Dropping pkt uid=%d", ch->uid()); */ drop(p, DROP_RTR_NO_ROUTE); #else status = ipq_set_verdict(h, pkt->packet_id, NF_DROP, 0, NULL); if (status < 0) die(h); #endif return; } route_discovery: /* Buffer packets... Packets are queued by the ip_queue.o module already. We only need to save the handle id, and return the proper verdict when we know what to do... */ #ifdef NS_PORT packet_queue_add(p, dest_addr); #else packet_queue_add(pkt->packet_id, dest_addr, ip); #ifdef CONFIG_GATEWAY /* In gateway mode we handle packets in userspace */ ipq_set_verdict(h, pkt->packet_id, NF_DROP, 0, NULL); #endif /* Already seeking the destination? Then do not allocate any memory or generate a RREQ. */ if (seek_list_find(dest_addr)) return; /* If the request is generated locally by an application, we save the IP header + 64 bits of data for sending an ICMP Destination Host Unreachable in case we don't find a route... */ if (src_addr.s_addr == DEV_IFINDEX(ifindex).ipaddr.s_addr && ip && pkt->data_len >= (ip->ihl << 2) + 8) { ipd = (struct ip_data *) malloc(sizeof(struct ip_data)); if (ipd == NULL) { perror("Malloc for IP data failed!"); exit(-1); } /* IP header + 64 bits data (8 bytes) */ ipd->len = (ip->ihl << 2) + 8; memcpy(ipd->data, ip, ipd->len); } else ipd = NULL; #endif if (fwd_rt && (fwd_rt->flags & RT_REPAIR)) rreq_local_repair(fwd_rt, src_addr, ipd); else rreq_route_discovery(dest_addr, rreq_flags, ipd); return; } else { #ifdef NS_PORT /* DEBUG(LOG_DEBUG, 0, "Sending pkt uid=%d", ch->uid()); */ sendPacket(p, fwd_rt->next_hop, 0.0); #else accept: if (pkt_flags & PKT_ENC || (pkt_flags & PKT_DEC)) status = ipq_set_verdict(h, pkt->packet_id, NF_ACCEPT, ntohs(ip->tot_len), (unsigned char *)ip); else status = ipq_set_verdict(h, pkt->packet_id, NF_ACCEPT, 0, NULL); if (status < 0) die(h); #endif /* When forwarding data, make sure we are sending HELLO messages */ gettimeofday(&this_host.fwd_time, NULL); if (!llfeedback && optimized_hellos) hello_start(); } }
static void * ip_noise_decide_what_to_do_with_packets_thread_func (void * void_context) { ip_noise_decide_what_to_do_with_packets_thread_context_t * context; ip_noise_messages_queue_t * packets_to_arbitrate_queue; int * terminate; ip_noise_message_t * msg_with_time; int status; struct ipq_handle * h; #ifdef DEBUG static int num; #endif ip_noise_verdict_t verdict; ip_noise_delayer_t * delayer; ip_noise_arbitrator_data_t * * data; ip_noise_flags_t * flags; ip_noise_arbitrator_packet_logic_t * packet_logic; context = (ip_noise_decide_what_to_do_with_packets_thread_context_t * )void_context; packets_to_arbitrate_queue = context->queue; terminate = context->terminate; h = context->h; delayer = context->delayer; data = context->data; flags = context->flags; free(context); packet_logic = ip_noise_arbitrator_packet_logic_alloc(data, flags); /* As long as another thread did not instruct us to terminate - loop! * */ while (! (*terminate)) { /* * Inside the loop, we dequeue an item from the queue, * decide what to do with it. If it should be dropped or released, * it is done immidiately. Else, it is placed in the delayer's priority * queue for release in the future. * */ msg_with_time = ip_noise_messages_queue_dequeue(packets_to_arbitrate_queue); if (msg_with_time == NULL) { usleep(500); continue; } #if 0 verdict = decide_what_to_do_with_packet(msg_with_time->m); #endif verdict = ip_noise_arbitrator_packet_logic_decide_what_to_do_with_packet(packet_logic, msg_with_time->m); if (verdict.action == IP_NOISE_VERDICT_ACCEPT) { #ifdef DEBUG #if 0 printf("Release Packet! (%i)\n", num++); #endif #endif status = ipq_set_verdict(h, msg_with_time->m->packet_id, NF_ACCEPT, 0, NULL); if (status < 0) { die(h); } free(msg_with_time); } else if (verdict.action == IP_NOISE_VERDICT_DROP) { #ifdef DEBUG printf("Dropping Packet! (%i)\n", num++); #endif status = ipq_set_verdict(h, msg_with_time->m->packet_id, NF_DROP, 0, NULL); if (status < 0) { die(h); } free(msg_with_time); } else if (verdict.action == IP_NOISE_VERDICT_DELAY) { #ifdef DEBUG printf("Delaying Packet! (%i)\n", num++); #endif ip_noise_delayer_delay_packet( delayer, msg_with_time, msg_with_time->tv, verdict.delay_len ); } else { *terminate = 1; fprintf(stderr, "Unknown Action!\n"); return NULL; } } return NULL; }
int doingDetection() { int status; struct nlmsghdr *nlh; struct ndpi_ethher *ethernet; struct ndpi_iphdr *iph; ipq_packet_msg_t *ipq_packet; int ip_len; struct ndpi_id_struct *src, *dst; struct ndpi_flow *flow; struct ndpi_flow_struct *ndpi_flow = NULL; u_int32_t protocol = 0; u_int8_t proto; u_int64_t time; static u_int64_t lasttime=0; unsigned char payload[1024*1024]; while(1) { status = ipq_read(h, buf, sizeof(buf),0); if(status==0||status==-1)continue; memset(payload, 0x00, sizeof(payload)); if(status > sizeof(struct nlmsghdr)) { nlh = (struct nlmsghdr *)buf;//测试是否和ndpi_ethher一致。 ipq_packet = ipq_get_packet(buf); ip_len=ipq_packet->data_len; time = ((uint64_t) ipq_packet->timestamp_sec) * detection_tick_resolution +ipq_packet->timestamp_usec / (1000000 / detection_tick_resolution); memcpy(payload + ETH_HDRLEN, ipq_packet->payload, ip_len); // printf("2\n"); if(lasttime > time) { time = lasttime; } lasttime = time; iph = (struct ndpi_iphdr *)(&(ipq_packet->payload[0]));//需要测试是否和pcap来的一致 if(iph) { // printf("before get_ndpi_flow\n"); flow = get_ndpi_flow(iph, ip_len,&src, &dst, &proto); // printf("after get_ndpi_flow\n"); } if(flow != NULL) { ndpi_flow = flow->ndpi_flow; flow->packets++, flow->bytes += ip_len; } else continue; // printf("3\n"); ip_packet_count++; total_bytes+=ip_len+24; if(flow->detection_completed) { /*ipq_set_verdict(h, ipq_packet->packet_id, NF_ACCEPT,ipq_packet->data_len,payload + ETH_HDRLEN);*/ ipq_set_mark(h,ipq_packet->packet_id,1); continue; } protocol = (const u_int32_t)ndpi_detection_process_packet(ndpi_struct, ndpi_flow,(char *)iph,ip_len, time, src, dst); // printf("4\n"); if((flow->detected_protocol != NDPI_PROTOCOL_UNKNOWN) || ((proto == IPPROTO_UDP) && (flow->packets > 8)) || ((proto == IPPROTO_TCP) && (flow->packets > 10))) { if(flow->detected_protocol==NDPI_PROTOCOL_UNKNOWN) flow->detected_protocol = ndpi_guess_undetected_protocol(ndpi_struct, flow->protocol, ntohl(flow->lower_ip), ntohs(flow->lower_port), ntohl(flow->upper_ip), ntohs(flow->upper_port)); flow->detection_completed = 1; protocol_counter[flow->detected_protocol]+=flow->packets; protocol_flows[flow->detected_protocol]++; protocol_counter_bytes[flow->detected_protocol]+=flow->bytes; snprintf(flow->host_server_name, sizeof(flow->host_server_name), "%s", flow->ndpi_flow->host_server_name); } ipq_set_verdict(h, ipq_packet->packet_id, NF_ACCEPT,ipq_packet->data_len,payload + ETH_HDRLEN); snprintf(flow->host_server_name, sizeof(flow->host_server_name), "%s", flow->ndpi_flow->host_server_name); } } }
/* returns a bound socket matching a connection request * * sets verdict on request packet if ipq or nfq was used and the port is already bound * * in the latter case, -1 is returned */ int get_boundsock(struct sockaddr_in *server_addr, uint16_t port, int type) { int fd, sockopt; #ifdef USE_IPQ_MON int status; #endif if ((type != SOCK_DGRAM) && (type != SOCK_STREAM)) { logmsg(LOG_ERR, 1, "Error - Socket type %d not supported.\n", type); exit(EXIT_FAILURE); } if (!(fd = socket(AF_INET, type, 0))) { logmsg(LOG_ERR, 1, "Error - Could not create socket: %m.\n"); exit(EXIT_FAILURE); } sockopt = 1; if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(sockopt)) < 0) logmsg(LOG_WARN, 1, "Warning - Unable to set SO_REUSEADDR for server socket.\n"); bzero((char *) server_addr, sizeof(struct sockaddr_in)); server_addr->sin_family = AF_INET; server_addr->sin_addr.s_addr = bind_address.s_addr; server_addr->sin_port = port; if ((bind(fd, (struct sockaddr *) server_addr, sizeof(struct sockaddr_in))) != 0) { /* we already got one server process */ logmsg(LOG_DEBUG, 1, "Unable to bind to port %u/tcp: %m.\n", ntohs(port)); #ifdef USE_IPQ_MON /* hand packet processing back to the kernel */ if ((status = ipq_set_verdict(h, packet->packet_id, NF_ACCEPT, 0, NULL)) < 0) { logmsg(LOG_ERR, 1, "Error - Could not set verdict on packet: %s.\n", ipq_errstr()); ipq_destroy_handle(h); exit(EXIT_FAILURE); } logmsg(LOG_DEBUG, 1, "IPQ - Successfully set verdict on packet.\n"); return(-1); #else #ifdef USE_NFQ_MON /* hand packet processing back to the kernel */ /* nfq_set_verdict()'s return value is undocumented, * but digging the source of libnetfilter_queue and libnfnetlink reveals * that it's just the passed-through value of a sendmsg() */ if (nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL) == -1) { logmsg(LOG_ERR, 1, "Error - Could not set verdict on packet.\n"); nfq_destroy_queue(qh); exit(EXIT_FAILURE); } logmsg(LOG_DEBUG, 1, "NFQ - Successfully set verdict on packet.\n"); /* a dynamic server is already present */ close(fd); return(-1); #else /* if bind() did not fail for 'port already in use' but for some other reason, * we're in troubles and want a verbose error message */ if (errno != 98) logmsg(LOG_NOISY, 1, "Warning - Could not bind to port %u/tcp: %m.\n", ntohs(port)); exit(EXIT_FAILURE); #endif #endif } logmsg(LOG_DEBUG, 1, "Socket created, file descriptor is %d.\n", fd); return(fd); }