/* check this every 1msec */ void CNatRxManager::handle_aging() { int i; dsec_t now=now_sec(); for (i=0; i<m_max_threads; i++) { CNatPerThreadInfo * thread_info=get_thread_info( i ); if ( thread_info->m_cur_nat_msg ) { if ( now - thread_info->m_last_time > MAX_TIME_MSG_IN_QUEUE_SEC ) { flush_node(thread_info); } } } }
void CNatRxManager::handle_packet_ipv4(CNatOption * option, IPHeader * ipv4) { CNatPerThreadInfo * thread_info=get_thread_info(option->get_thread_id()); if (!thread_info) { return; } /* Extract info from the packet ! */ uint32_t ext_ip = ipv4->getSourceIp(); uint32_t ext_ip_server = ipv4->getDestIp(); uint8_t proto = ipv4->getProtocol(); /* must be TCP/UDP this is the only supported proto */ if (!( (proto==6) || (proto==17) )) { m_stats.m_err_no_valid_proto++; return; } /* we support only TCP/UDP so take the source port , post IP header */ UDPHeader * udp= (UDPHeader *) (((char *)ipv4)+ ipv4->getHeaderLength()); uint16_t ext_port = udp->getSourcePort(); #ifdef NAT_TRACE_ printf("rx msg ext ip : %08x:%08x ext port : %04x flow_id : %d \n",ext_ip,ext_ip_server,ext_port,option->get_fid()); #endif CGenNodeNatInfo * node=thread_info->m_cur_nat_msg; if ( !node ) { node = (CGenNodeNatInfo * )CGlobalInfo::create_node(); assert(node); node->init(); thread_info->m_cur_nat_msg = node; thread_info->m_last_time = now_sec(); } /* get message */ CNatFlowInfo * msg=node->get_next_msg(); /* fill the message */ msg->m_external_ip = ext_ip; msg->m_external_ip_server = ext_ip_server; msg->m_external_port = ext_port; msg->m_fid = option->get_fid(); msg->m_pad = 0xee; if ( node->is_full() ) { flush_node(thread_info); } }
static uint64_t flush_node (FILE *fp, int features, struct memnode *mp, uint64_t *cntp) { uint64_t curpos, refpos, pos, cnt, tcnt; struct memnode *tp; if (mp == NULL) return 0; tp = mp; while (tp) { if (tp->child) { tp->childpos = flush_node (fp, features, tp->child, &(tp->subcnt)); tp->child = NULL; } tp = tp->sib; } curpos = ftell64 (fp); pos = curpos; refpos = pos; cnt = 0; while (mp) { tcnt = mp->subcnt; if (mp->end) tcnt++; trie_node_write (fp, features, &refpos, &pos, tcnt, mp->len, mp->end, mp->childpos, mp->dat); cnt += tcnt; tp = mp; mp = mp->sib; delnode (tp); } trie_node_write (fp, features, NULL, NULL, 0, 0, 0, 0, NULL); *cntp = cnt; return curpos; }
/* * This addline version assumes sorted input. This means that whenever * a split occurs all subtrees can be flushed. */ static void addline_trie (FILE *fp, int features, struct memnode **mpp, unsigned char *dat, int len) { /* Previous sib. Points to the last sib */ /* visited, or NULL is this is the first*/ /* sib in the node. */ struct memnode *prvsibp = NULL; while (len && dat[len-1] == '\n') len--; if (!len) return; for (;;) { int l1, l2, ct; unsigned char *d1, *d2; struct memnode *mp, *n1, *n2; mp = *mpp; /* In case of an empty trie: build one */ if (mp == NULL) { mp = newnode (dat, len); mp->end = 1; *mpp = mp; /* As the input is sorted, we won't*/ /* change the older sibs! So flush */ /* and forget prvsibp's subtrie */ if (prvsibp) { prvsibp->childpos = flush_node (fp, features, prvsibp->child, &(prvsibp->subcnt)); prvsibp->child = NULL; fflush (fp); } return; } /* Move to the next sib if appropriate */ if (len && dat[0] > mp->dat[0]) { prvsibp = mp; mpp = &(mp->sib); continue; } /* Introduce a new sib if appropriate */ if (len && dat[0] < mp->dat[0]) { abort_error (); } /* We found the right sib */ ct = 0; d1 = dat; l1 = len; d2 = mp->dat; l2 = mp->len; /* At what pos do the sib and the new */ /* value differ */ while (l1 && l2 && *d1 == *d2) { ct++; d1++; l1--; d2++; l2--; } if (!l2) { /* No sib string data left */ if (!l1) { /* No input string left as well*/ /* So we have a match! */ if (mp->child || mp->childpos) { abort_error (); } mp->end = 1; return; } /* Some input string data is left */ /* so the string is a child of sib */ /* Continue there */ mpp = &(mp->child); dat = d1; len = l1; prvsibp = NULL; continue; } /* There's unmatched sib string data */ /* left, so split the node */ if (!l1) { abort_error (); } /* New node n2 is the non matching tail*/ /* of mp */ n2 = newnode (d2, l2); n2->child = mp->child; n2->end = mp->end; /* New node n1 replaces mp, which has */ /* The prefix length ct of mp */ n1 = newnode (mp->dat, ct); n1->sib = mp->sib; n1->child = n2; *mpp = n1; /* mp is obsolete now */ delnode (mp); /* If there's no input string data left*/ /* Then the mp replacement n1 is an */ /* endpoint! */ if (!l1) { n1->end = 1; return; }; /* Now move on to the child, where the */ /* remainder of the input string will */ /* reside */ mpp = &(n1->child); dat = d1; len = l1; prvsibp = NULL; } }
void pop_nest(void) { flush_node(cur_list.head_field); decr(nest_ptr); }