// dump rules in my format void my_dump_rule(Rule *rule) { int i; Range r; printf("rule[%4d]:\t", rule->id); // dump SIP & DIP for (i = 0; i < 2; i++) { r = rule->field[i]; if (r.lo == r.hi) dump_ip(r.lo); else if (r.lo == 0 && r.hi == 0xffffffff) printf("*"); else { dump_ip(r.lo); printf("/%d", 31-MSB(r.hi-r.lo+1)); } printf(", "); } // dump SP & DP for (i = 2; i < 4; i++) { r = rule->field[i]; if (r.lo == r.hi) printf("%x", r.lo); else if (r.lo == 0 && r.hi == 0xffff) printf("*"); else { printf("[%x-%x]", r.lo, r.hi); } printf(", "); } // dump proto r = rule->field[4]; if (r.lo == r.hi) printf("%d", r.lo); else if (r.lo == 0 && r.hi == 0xff) printf("*"); else printf("[%d-%d]", r.lo, r.hi); printf("\n"); }
/* This dumps a complete udp frame, starting from the eth header */ int dump_udppkt(char *prefix, void *buf, int len, struct TimeInternal *ti) { struct ethhdr *eth = buf; struct iphdr *ip = buf + ETH_HLEN; struct udphdr *udp = (void *)(ip + 1); void *payload = (void *)(udp + 1); if (ti) dump_time(prefix, ti); dump_eth(prefix, eth); dump_ip(prefix, ip); dump_udp(prefix, udp); dump_payload(prefix, payload, len - (payload - buf)); return 0; }
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; }