unsigned int sec_url_filter_hook( unsigned int hook_no, struct sk_buff *skb, const struct net_device *dev_in, const struct net_device *dev_out, int (*handler)(struct sk_buff *)) { unsigned int verdict = NF_ACCEPT; if (filterMode) { if (skb != NULL) { struct iphdr *iph = (struct iphdr*) ip_hdr(skb); if (iph != NULL) { if (iph->protocol == 6) // TCP case { int delFlag = 0; struct tcphdr *tcph = (struct tcphdr *)skb_transport_header(skb); tcp_TrackInfo *rejected = NULL; if (tcph!= NULL) { delFlag = (tcph->fin || tcph->rst); } verdict = NF_QUEUE; rejected = find_tcp_TrackInfo(rejected_TrackInfo, skb, delFlag); // If this is FIN packet, remove TCP Info. if (rejected != NULL) // This is Rejected { verdict = NF_DROP; } if (delFlag == 1) { tcp_TrackInfo *gettingNode = NULL; verdict = NF_ACCEPT; if (rejected != NULL) { free_tcp_TrackInfo(rejected); } gettingNode = find_tcp_TrackInfo(getting_TrackInfo, skb, 1); // Find previous TCP Track Info and remove from list free_tcp_TrackInfo(gettingNode); } } } } } return verdict; }
void clean_tcp_TrackInfos(tcp_Info_Manager *manager) { unsigned long flags = 0; tcp_TrackInfo *node = NULL; if (manager != NULL) { SEC_spin_lock_irqsave(&manager->tcp_info_lock, flags); while (manager->head != NULL) { node = manager->head; manager->head = manager->head->next; if (node->q_entry != NULL) { nf_reinject((struct nf_queue_entry *)node->q_entry, NF_DROP); node->q_entry = NULL; } free_tcp_TrackInfo(node); } manager->tail = NULL; manager->count = 0; SEC_spin_unlock_irqrestore(&manager->tcp_info_lock, flags); } }
// sec_filter driver write function ssize_t sec_url_filter_write( struct file *filp, const char *buf, size_t count, loff_t *f_pos) { int result = -EIO; if ((buf != NULL) && (count >4)) { short version = *(short *)buf; int cmd = *(int *)(buf+sizeof(short)); char *data = (char *)(buf+sizeof(short)+sizeof(int)); { if (version == 0) { switch(cmd) { case SET_FILTER_MODE: // Turn On and Off filtering. { filterMode = *(int *)data; result = count; if (filterMode == FILTER_MODE_OFF) { wake_up_interruptible(&user_noti_Q); clean_tcp_TrackInfos(getting_TrackInfo); clean_tcp_TrackInfos(rejected_TrackInfo); clean_tcp_TrackInfos(notifying_TrackInfo); clean_tcp_TrackInfos(notified_TrackInfo); SEC_FREE(exceptionURL); SEC_FREE(errorMsg); } printk(KERN_INFO "SEC URL Filter Mode : %d\n", filterMode); } break; case SET_USER_SELECT: //version 2, id 4, choice 2 { tcp_TrackInfo *selectInfo = NULL; int id = *((int *)(data)); int choice = *((int *)(data+sizeof(unsigned int))); unsigned int verdict = NF_DROP; struct nf_queue_entry *entry= NULL; selectInfo = find_tcp_TrackInfo_withID(notified_TrackInfo, id, 1); if (selectInfo != NULL) { result = count; entry = (struct nf_queue_entry *)selectInfo->q_entry; selectInfo->q_entry = NULL; selectInfo->status = choice; if (choice == ALLOW || ((filterMode == FILTER_MODE_ON_RESPONSE)||(filterMode == FILTER_MODE_ON_RESPONSE_REFER))) { verdict = NF_ACCEPT; //Response case should send packet } if (choice == BLOCK) { add_tcp_TrackInfo(rejected_TrackInfo, selectInfo); // Add this node to Rejected List. } else { free_tcp_TrackInfo(selectInfo); } nf_reinject(entry, verdict); // Reinject packet with the verdict } else { printk("SEC_FILTER_URL : NO SUCH ID\n"); } } break; case SET_EXCEPTION_URL: { int urlLen = *((int *)(data)); SEC_FREE(exceptionURL); exceptionURL = SEC_MALLOC(urlLen+1); if (exceptionURL != NULL) { memcpy(exceptionURL, (data+sizeof(int)), urlLen); result = count; } } break; case SET_ERROR_MSG: { int msgLen = *((int *)(data)); SEC_FREE(errorMsg); errMsgSize = 0; errorMsg = SEC_MALLOC(msgLen+1); if (errorMsg != NULL) { memcpy(errorMsg, (data+sizeof(int)), msgLen); errMsgSize = msgLen; result = count; } } break; } } } } return result; }
int sec_url_filter_slow(struct nf_queue_entry *entry, unsigned int queuenum) { if (entry != NULL) { if (filterMode) { struct sk_buff *skb = entry->skb; char *request = NULL; tcp_TrackInfo *gettingNode = NULL; tcp_TrackInfo *notifyNode = NULL; if (skb != NULL) { struct iphdr *iph = (struct iphdr*)ip_hdr(skb); if (iph != NULL) { if (iph->protocol == 6) { struct tcphdr *tcph = (struct tcphdr *)skb_transport_header(skb); if (tcph!= NULL) { notifyNode = find_tcp_TrackInfo(notifying_TrackInfo, skb, 0); if (notifyNode != NULL) // If this is already notified to user, drop it. { unsigned int verdict = NF_DROP; nf_reinject(entry, verdict); return 0; } gettingNode = find_tcp_TrackInfo(getting_TrackInfo, skb, 1); // Find previous TCP Track Info and remove from list if (gettingNode == NULL) // No previous Info { gettingNode = isURL(skb); // If this is URL Request then make TCP Track Info } if (gettingNode != NULL) { request = getPacketData(skb, gettingNode); // Get Packet if (request != NULL) // If there is packet data { getURL(request, gettingNode); // Get URL and update status kfree(request); request = NULL; if (gettingNode->status == GOT_FULL_URL) // If get Full URL, then make notify info { makeNotifyInfo(gettingNode); if ((exceptionURL != NULL) && (gettingNode->url !=NULL)) { if (strstr(&gettingNode->url[sizeof(URL_Info)], exceptionURL) != NULL) // This is exception URL { free_tcp_TrackInfo(gettingNode); nf_reinject(entry, NF_ACCEPT); return 0; } } gettingNode->q_entry = entry; add_tcp_TrackInfo(notifying_TrackInfo, gettingNode); wake_up_interruptible(&user_noti_Q); // Wake Up read function return 0; } } add_tcp_TrackInfo_ToHead(getting_TrackInfo, gettingNode); } } } } } } nf_reinject(entry, NF_ACCEPT); } return 0; }