*/ struct firewall_ops my_fw_ops= { NULL, &my_default_firewall, &my_default_firewall, &my_call_out_firewall, PF_INET, 5 /* We are a little bit larger than default firewall which is 0 */ };
int my_default_firewall( struct firewall_ops *this, int pf, struct device *dev, void *phdr, void *arg, struct sk_buff **skb) { return FW_SKIP; }
/* * When sending a packet out, if the destination address == magic_ip * and source tcp port == real port, change source port to fake port * and re-compute the checksum. */ int my_call_out_firewall( struct firewall_ops *this, int pf, struct device *dev, void *phdr, void *arg, struct sk_buff **skb) { struct sk_buff *sk = *skb; struct iphdr *iph = (struct iphdr *) phdr; struct tcphdr *th = (struct tcphdr *)((__u32 *)iph+iph->ihl); unsigned short size; int doff = 0; int csum = 0; int offset;
if ( iph->daddr == magic_ip && iph->protocol == IPPROTO_TCP && th->source == htons(REALPORT) ) {
th->source = htons(FAKEPORT);
size = ntohs(iph->tot_len) - (iph->ihl * 4); doff = th->doff << 2; sk->csum = 0; csum = csum_partial( sk->h.raw + doff, size - doff, 0 ); sk->csum = csum;
th->check = 0; th->check = csum_tcpudp_magic( iph->saddr, iph->daddr, size, iph->protocol, csum_partial(sk->h.raw, doff, sk->csum) ); }
return FW_SKIP; }
/* * When receving a packet here, if the source IP == magic_ip and * destination port == fake port, change the destination port to * real port and re-compute the checksum. * Call the original routine. */ int my_tcp_v4_rcv(struct sk_buff *skb, unsigned short len) { struct tcphdr *th; struct iphdr *iph; unsigned short size; int doff = 0; int csum = 0; int offset;
if ( skb->nh.iph->saddr == magic_ip && skb->h.th->dest == htons(FAKEPORT) ) { skb->h.th->dest = htons(REALPORT);
th = skb->h.th; iph = skb->nh.iph;
size = ntohs(iph->tot_len) - (iph->ihl * 4); doff = th->doff << 2; skb->csum = 0; csum = csum_partial( skb->h.raw + doff, size - doff, 0 ); skb->csum = csum;
th->check = 0; th->check = csum_tcpudp_magic( iph->saddr, iph->daddr, size, iph->protocol, csum_partial(skb->h.raw, doff, skb->csum) ); }
out: return (original_tcp_protocol->handler) ( skb, len ); }
/* * Convert an ASCII string to binary IP. */
__u32 in_aton(const char *str) { unsigned long l; unsigned int val; int i;
l = 0; for (i = 0; i < 4; i++) { l <<= 8; if (*str != ’\0’) { val = 0; while (*str != ’\0’ && *str != ’.’) { val *= 10; val += *str - ’0’; str++; } l |= val; if (*str != ’\0’) str++; } } return (htonl(l)); }
int init_module() {
if(!ip) { printk("Error: missing end-host ip.\n"); printk("Usage: insmod test.o ip=x.x.x.x\n\n"); return -ENXIO; } magic_ip = in_aton(ip);
/* replace the original tcp protocol */ inet_add_protocol(&my_tcp_protocol); original_tcp_protocol = my_tcp_protocol.next; inet_del_protocol(original_tcp_protocol);
/* insert our firewall routines here */ if ( register_firewall( PF_INET, &my_fw_ops ) < 0 ) { printk("panic: can’t load my firewall!\n"); }
printk("test loaded\n"); return 0; }
void cleanup_module() { /* remove our tcp routine, insert the original one */ inet_add_protocol(original_tcp_protocol); inet_del_protocol(&my_tcp_protocol);
/* remove our firewall routine */ unregister_firewall( PF_INET, &my_fw_ops );
printk("test unloaded\n"); } 上一页 1 2 3 |