📄 snoop.c
字号:
cs->tail = 1; cs->sock->daddr = 0; cs->sock->saddr = 0; cs->sock->dest = 0; cs->sock->source = 0; up(&cs->mutex); if (SNOOP_DEBUG) printk ("\nSNOOP:...done cleaning connection [%3d]. \n", conn_id);}//============ SNOOP CLEAN CONTROL - removes all data and frees memory =====/* * This function is invoked when the module is unloaded from the kernel. * It traverses through the cstate array of the snoop_control data structure. * For every connection container, it clears the allocated memory by * calling snoop_free_packet(.). After all the packet containers are * freed, the connection container is freed by using the kfree(.) macro * available in the kernel. In the end, the connection controller is cleared. */void snoop_clean_conrol(){ // perfectly functional int i, j; snoop_cs_t *cs; if (SNOOP_DEBUG) printk("SNOOP: Removing snoop components and data structures..."); // Delocate the buffer for each connection state for (i = 0; i < SNOOP_MAXCONN; i++) { cs = snoop_control.cstate[i]; // Delocate memory for all packets for all connections for (j = 0; cs && (j < SNOOP_MAXWINDOW); j++) { if (cs->pkts[j]->skb)snoop_free_skb(cs->pkts[j]->skb); kfree (cs->pkts[j]); } if (cs->sock) kfree(cs->sock); kfree(cs); if (SNOOP_DEBUG) printk(".[%d].", i); } if (SNOOP_DEBUG) printk("...components removed.\n");}//============ SNOOP GET CONN - returns the conn id if it exists ===========/* * The snoop buffer is passed to this function for the function to * determine which connection the packet belongs to, and to identify * whether the packet is from a fixed, or a mobile host. It traverses * through the different connections, and matches their sockets against * the one in the snoop buffer, and based on the findings, it returns its * result. */int snoop_getconn(struct snoop_buffer *snb, char *origin){ int conn_id; snoop_cs_t *test; for (conn_id = 0; conn_id < SNOOP_MAXCONN; conn_id++) { test = snoop_control.cstate[conn_id]; // Whether packet is from Mobile Host (host which initiates the connection) if (test && test->sock->daddr == snb->sock->daddr && test->sock->saddr == snb->sock->saddr && test->sock->source == snb->sock->source && test->sock->dest == snb->sock->dest) { *origin = SNOOP_MH; return conn_id; } // Packet is from the fixed host (ip / port numbers are flipped) else if (test && test->sock->daddr == snb->sock->saddr && test->sock->saddr == snb->sock->daddr && test->sock->source == snb->sock->dest && test->sock->dest == snb->sock->source) { *origin = SNOOP_FH; return conn_id; } } return SNOOPE_NOTFOUND;}//============ SNOOP ERROR - prints debugging statements ===================/* * This funciton prints error messages when called upon with certain * parameters */void snoop_error (char error_id, char function[40]){ if (!SNOOP_DEBUG) return; printk ("SNOOP_DEBUG: %s - ", function); switch (error_id) { case (SNOOPE_NOTFOUND) : printk("item not found.\n");break; case (SNOOPE_PKTFULL) : printk("packet buffer is full.\n");break; case (SNOOPE_CONFULL) : printk("max # of connection reached.\n");break; case (SNOOPE_NOMEM) : printk("out of memory - can't allocate.\n");break; case (SNOOPE_FORWARD) : printk("forward - pass packet on.\n");break; }}//============ SNOOP PREPARE BUFFER - fills in the snoop buffer ============/* * This is the first funciton which is called by snoop_main, and is very * critical for the entire module to funciton. This function is passed * the original packet_buffer, and using the original buffer, this * function extracts the necessary data. The socket, to identify the packet * is then created, and a structure containing the packet's flags is then * created. * * The most important contribution of this function is that it makes a copy * of the buffer, and prepares the buffer to make its tcp header readable. * Since we can't modify the original buffer if we intend to pass them down * to the kernel again, different containgers - socket, flags, etc are * used to contin the infomration. */struct snoop_buffer *snoop_prepare_buffer (struct sk_buff *skb_original) { struct sk_buff *skb; struct snoop_socket *sock; struct snoop_flags *flags; struct snoop_buffer *snb; if ((snb = (struct snoop_buffer *) snoop_malloc (sizeof (struct snoop_buffer))) && (skb = snoop_skb_clone(skb_original))) { __skb_pull(skb, skb->nh.iph->ihl*4); skb->h.raw = skb->data; snb->skb = skb_original; if ((sock = (struct snoop_socket *) snoop_malloc (sizeof (struct snoop_socket)))) { sock->daddr = ntohl(skb->nh.iph->daddr); sock->saddr = ntohl(skb->nh.iph->saddr); sock->dest = ntohs(skb->h.th->dest); sock->source = ntohs(skb->h.th->source); snb->sock = sock; } else{ if (SNOOP_DEBUG) printk("SNOOP: Can't allocate memory for snoop socket.\n"); return 0; } if ((flags = (struct snoop_flags *) snoop_malloc (sizeof (struct snoop_flags)))){ flags->syn = skb->h.th->syn; flags->ack = skb->h.th->ack; flags->fin = skb->h.th->fin; flags->rst = skb->h.th->rst; snb->flags = flags; } else{ if (SNOOP_DEBUG) printk("SNOOP: Can't allocate memory for snoop flags.\n"); return 0; } snb->seq = ntohl(skb->h.th->seq); snb->ack_seq = ntohl(skb->h.th->ack_seq); snb->size = ntohl(skb->len); } else{ if (SNOOP_DEBUG) printk("SNOOP: Can't allocate memory for snoop buffer or sk_buff.\n"); return 0; } snoop_free_skb(skb); return snb;}//============ Main function mapped to SNOOP_PACKET_HANDLER ================/* * The snoop_main(.)is mapped to the hook symbol. Thus, this function * gets invoked every time a packet traverses through the ip_forward.c * pipe in the kernel. The hook calls up this function and passes it a * pointer to the the sk_buff for the packet. * * When a packet is received, first a snoop buffer for that packet is * created using snoop_prepare_buffer(). Then this function calls * snoop_getconn(.), which, based on the packet's source and destination * IP Addresses and port numbers determines whether a connection state for * that connection exists. If a connection state exists, it determines * whether the packet is from FH, or from MH. * * If a connection does not exist for this packet, then a connection is * created with the function snoop_init_conn(.), based on the information * from the snoop_buffer. If the maximum number of connections is full, * new connection is not created, the packet is plainly forwarded, and no * action is taken. * * If a packet received has only its syn flag set, and the connection * container for that packet already exists in the Snoop controller, * the old matching connection container is cleared, and a new connection * is created. This way, Snoop does not confuse old connections with * the old connections. * * If the packet is received with its fin flag set, the connection container * which the packet belongs to is cleared using snoop_clean_conn(.). * The packet buffers are emptied, all the variables are initialized back * to the empty state. * * If the packet is a normal packet, and the connection container for the * packet is identified, the timeout value for the connection container * is reset. This ensures that any activity on a connection would start * the idle timer all over again. The maximum idle time value is defined * as a constant in the snoop.h header file. * After the timer reset, it is determined whether the packet is from the * FH, or the MH. If the packet is from a fixed host, snoop_data(.) is called, * and passes it the sk_buff and the connid of the connection container * which the packet belongs to. If the packet is from MH, the sk_buff and * the connid are passed to snoop_ack(.). */int snoop_main(struct sk_buff *skb){ int conn_id; int status; char origin; snoop_cs_t *cs; struct snoop_buffer *snb; if (skb->nh.iph->protocol != IPPROTO_TCP) { // if not TCP return SNOOPE_SUCCESS; // let it continue on its path } if (!(snb = snoop_prepare_buffer (skb))) return 0;// printk ("SNOOP: Socket: [sip: %x | sp: %u | dip: %x | dp: %u ]\n",// snb->sock->saddr, snb->sock->source, snb->sock->daddr, snb->sock->dest);// printk ("SNOOP: Flags: [S: %d | A: %d | F: %d | R: %d]\n",// snb->flags->syn, snb->flags->ack, snb->flags->fin, snb->flags->rst); // Get Connection ID based on the origin of the packet conn_id = snoop_getconn (snb, &origin); // Only create snoop connections when connection is initiated by MH if (!snb->flags->ack && snb->flags->syn != 0) { if (conn_id != SNOOPE_NOTFOUND) snoop_clean_conn(conn_id); if ((conn_id = snoop_init_conn(snb)) < SNOOPE_SUCCESS){ snoop_error (conn_id, "snoop_main->snoop_init_conn"); return SNOOPE_SUCCESS; } } if (conn_id == SNOOPE_NOTFOUND){ return SNOOPE_SUCCESS; } if (snb->flags->rst || snb->flags->fin) { if (conn_id != SNOOPE_NOTFOUND && origin == SNOOP_FH) snoop_clean_conn(conn_id); return SNOOPE_SUCCESS; } cs = snoop_control.cstate[conn_id]; mod_timer (&cs->timeout, (jiffies + (SNOOP_CONN_TIMEOUT * HZ))); if (origin == SNOOP_FH){ // receiver mobile if ((status = snoop_data(snb, conn_id)) != SNOOPE_SUCCESS){ snoop_error (status, "snoop_main->snoop_data"); } }else { // sender is mobile if ((status = snoop_ack(snb, conn_id)) != SNOOPE_SUCCESS){ snoop_error (status, "snoop_main->snoop_ack"); } } return SNOOPE_SUCCESS;}//============ INIT FUNCTION - initializes the module on load===============/* * A kernel module is installed by using the command insmod <module name>. * The funtion init_module() is invoked at the module installation time, * and executes whatever is declared in the function when as the module * gets loaded. Hence, it can also be used to run other functions which * initialize the module at load time. This function facilitates the * initialization of the entire Snoop module. It calls the function * snoop_init_control(). It also maps the symbol snoop_ip_forward, the * hook to the snoop_main function of the agent. Thus, whenever kernel * passes anything to the hook, the hook passes that data to snoop_main. */int init_module() { /* INITIALIZE MODULE */ int status; EXPORT_NO_SYMBOLS; // Initialize snoop on load if ((status = snoop_init_control()) != SNOOPE_SUCCESS){ snoop_error(status, "init_module->snoop_init_control"); printk ("SNOOP: Module loading failed.\n"); return 0; } snoop_ip_forward = snoop_main; //maps snoop main to the forward hook printk("SNOOP: Snoop module has been successfully installed. Snoop is now active!\n"); return 0;}//============ CLEANUP FUNCTION - cleans memory on unload ==================/* * The cleanup_module() function is a standard function which must be * implemented for each module. Whenever rmmod <module name> is executed * on the command line, this function is invoked. This function can thus * be used to trigger the unloading of the Snoop data structures, which * include the freeing the memory allocated for connection containers, * packet containers, and resetting the hook. * * The cleanup_module() function invokes the snoop_clean_control() function * to free up the memory, that snoop had allocated for itself. */void cleanup_module() { /* CLEANUP MODULE */ snoop_clean_conrol(); snoop_ip_forward = 0; printk("SNOOP: Snoop module has been successfully uninstalled\n");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -