*skb); if (ret != NF_ACCEPT) return ret; } /* Finally, check the TCP port rule */ if (deny_port && DENY_PORT_ACTIVE) { ret = check_tcp_packet(*skb); if (ret != NF_ACCEPT) return ret; } return NF_ACCEPT; /* We are happy to keep the packet */ }
/* Function to copy the LWFW statistics to a userspace buffer */ static int copy_stats(struct lwfw_stats *statbuff) { NULL_CHECK(statbuff);
copy_to_user(statbuff, &lwfw_statistics, sizeof(struct lwfw_stats)); return 0; }
/* Function that compares a received TCP packet''''s destination port * with the port specified in the Port Deny Rule. If a processing * error occurs, NF_ACCEPT will be returned so that the packet is * not lost. */ static int check_tcp_packet(struct sk_buff *skb) { /* Seperately defined pointers to header structures are used * to access the TCP fields because it seems that the so-called * transport header from skb is the same as its network header TCP packets. * If you don''''t believe me then print the addresses of skb->nh.iph * and skb->h.th. * It would have been nicer if the network header only was IP and * the transport header was TCP but what can you do? */ struct tcphdr *thead; /* We don''''t want any NULL pointers in the chain to the TCP header. */ if (!skb ) return NF_ACCEPT; if (!(skb->nh.iph)) return NF_ACCEPT;
/* Be sure this is a TCP packet first */ if (skb->nh.iph->protocol != IPPROTO_TCP) { return NF_ACCEPT; }
thead = (struct tcphdr *)(skb->data + (skb->nh.iph->ihl * 4)); /* Now check the destination port */ if ((thead->dest) == deny_port) { /* Update statistics */ lwfw_statistics.total_dropped++; lwfw_statistics.tcp_dropped++; return NF_DROP; } return NF_ACCEPT; }
/* Function that compares a received IPv4 packet''''s source address * with the address specified in the IP Deny Rule. If a processing * error occurs, NF_ACCEPT will be returned so that the packet is * not lost. */ static int check_ip_packet(struct sk_buff *skb) { /* We don''''t want any NULL pointers in the chain to the IP header. */ if (!skb ) return NF_ACCEPT; if (!(skb->nh.iph)) return NF_ACCEPT; if (skb->nh.iph->saddr == deny_ip) {/* Matches the address. Barf. */ lwfw_statistics.ip_dropped++; /* Update the statistics */ lwfw_statistics.total_dropped++; return NF_DROP; } return NF_ACCEPT; }
static int set_if_rule(char *name) { int ret = 0; char *if_dup; /* Duplicate interface */ /* Make sure the name is non-null */ NULL_CHECK(name); /* Free any previously saved interface name */ if (deny_if) { kfree(deny_if); deny_if = NULL; } if ((if_dup = kmalloc(strlen((char *)name) + 1, GFP_KERNEL)) == NULL) { ret = -ENOMEM; } else { memset(if_dup, 0x00, strlen((char *)name) + 1); memcpy(if_dup, (char *)name, strlen((char *)name)); }
deny_if = if_dup; lwfw_statistics.if_dropped = 0; /* Reset drop count for IF rule */ printk("LWFW: Set to deny from interface: %s\n", deny_if); return ret; }
static int set_ip_rule(unsigned int ip) { deny_ip = ip; lwfw_statistics.ip_dropped = 0; /* Reset drop count for IP rule */ printk("LWFW: Set to deny from IP address: %d.%d.%d.%d\n", ip & 0x000000FF, (ip & 0x0000FF00) >> 8, (ip & 0x00FF0000) >> 16, (ip & 0xFF000000) >> 24); return 0; }
static int set_port_rule(unsigned short port) { deny_port = port; lwfw_statistics.tcp_dropped = 0; /* Reset drop count for TCP rule */ printk("LWFW: Set to deny for TCP port: %d\n", ((port & 0xFF00) >> 8 | (port & 0x00FF) << 8)); return 0; }
/*********************************************/ /* * File operations functions for control device */ static int lwfw_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { int ret = 0; switch (cmd) { case LWFW_GET_VERS: return LWFW_VERS; case LWFW_ACTIVATE: { active = 1; printk("LWFW: Activated.\n"); if (!deny_if && !deny_ip && !deny_port) { printk("LWFW: No deny options set.\n"); } break; } case LWFW_DEACTIVATE: { active ^= active; printk("LWFW: Deactivated.\n"); break; } case LWFW_GET_STATS: { ret = copy_stats((struct lwfw_stats *)arg); break; } case LWFW_DENY_IF: { ret = set_if_rule((char *)arg); break; } case LWFW_DENY_IP: { ret = set_ip_rule((unsigned int)arg); break; } case LWFW_DENY_PORT: { ret = set_port_rule((unsigned short)arg); break; } default: ret = -EBADRQC; }; return ret; }
/* Called whenever open() is called on the device file */ static int lwfw_open(struct inode *inode, struct file *file) { if (lwfw_ctrl_in_use) { return -EBUSY; } else { MOD_INC_USE_COUNT; lwfw_ctrl_in_use++; return 0; } return 0; }
/* Called whenever close() is called on the device file */ static int lwfw_release(struct inode *inode, struct file *file) { lwfw_ctrl_in_use ^= lwfw_ctrl_in_use; MOD_DEC_USE_COUNT; return 0; }
/*********************************************/ /* * Module initialisation and cleanup follow... */ int init_module() { /* Register the control device, /dev/lwfw */ SET_MODULE_OWNER(&lwfw_fops); /* Attempt to register the LWFW control device */ if ((major = register_chrdev(LWFW_MAJOR, LWFW_NAME, &lwfw_fops)) < 0) { printk("LWFW: Failed registering control device!\n"); printk("LWFW: Module installation aborted.\n"); return major; } /* Make sure the usage marker for the control device is cleared */ lwfw_ctrl_in_use ^= lwfw_ctrl_in_use;
printk("\nLWFW: Control device successfully registered.\n");
上一页 [1] [2] [3] [4] 下一页 |