All pastes #82230 Raw Edit

Someone

public text v1 · immutable
·published 2006-07-08 05:33 UTC
rendered paste body
void divert_frame(struct sk_buff *skb)
{
        struct ethhdr                   *eth = eth_hdr(skb);
        struct iphdr                    *iph;
        struct tcphdr                   *tcph;
        struct udphdr                   *udph;
        struct divert_blk               *divert = skb->dev->divert;
        int                             i, src, dst;
        unsigned char                   *skb_data_end = skb->data + skb->len;

        /* Packet is already aimed at us, return */
        if (!memcmp(eth, skb->dev->dev_addr, ETH_ALEN))
                return;

        /* proto is not IP, do nothing */
        if (eth->h_proto != htons(ETH_P_IP))
                return;

        /* Divert all IP frames ? */
        if (divert->protos & DIVERT_PROTO_IP) {
                ETH_DIVERT_FRAME(skb);
                return;
        }

        /* Check for possible (maliciously) malformed IP frame (thanks Dave) */
        iph = (struct iphdr *) skb->data;
        if (((iph->ihl<<2)+(unsigned char*)(iph)) >= skb_data_end) {
                printk(KERN_INFO "divert: malformed IP packet !\n");
                return;
        }

        switch (iph->protocol) {
        /* Divert all ICMP frames ? */
        case IPPROTO_ICMP:
                if (divert->protos & DIVERT_PROTO_ICMP) {
                        ETH_DIVERT_FRAME(skb);
                        return;
                }
                break;

        /* Divert all TCP frames ? */
        case IPPROTO_TCP:
                if (divert->protos & DIVERT_PROTO_TCP) {
                        ETH_DIVERT_FRAME(skb);
                        return;
                }

                /* Check for possible (maliciously) malformed IP
                 * frame (thanx Dave)
                 */
                tcph = (struct tcphdr *)
                        (((unsigned char *)iph) + (iph->ihl<<2));
                if (((unsigned char *)(tcph+1)) >= skb_data_end) {
                        printk(KERN_INFO "divert: malformed TCP packet !\n");
                        return;
                }

                /* Divert some tcp dst/src ports only ?*/
                for (i = 0; i < MAX_DIVERT_PORTS; i++) {
                        dst = divert->tcp_dst[i];
                        src = divert->tcp_src[i];
                        if ((dst && dst == tcph->dest) ||
                            (src && src == tcph->source)) {
                                ETH_DIVERT_FRAME(skb);
                                return;
                        }
                }
                break;

        /* Divert all UDP frames ? */
        case IPPROTO_UDP:
                if (divert->protos & DIVERT_PROTO_UDP) {
                        ETH_DIVERT_FRAME(skb);
                        return;
                }

                /* Check for possible (maliciously) malformed IP
                 * packet (thanks Dave)
                 */
                udph = (struct udphdr *)
                        (((unsigned char *)iph) + (iph->ihl<<2));
                if (((unsigned char *)(udph+1)) >= skb_data_end) {
                        printk(KERN_INFO
                               "divert: malformed UDP packet !\n");
                        return;
                }

                /* Divert some udp dst/src ports only ? */
                for (i = 0; i < MAX_DIVERT_PORTS; i++) {
                        dst = divert->udp_dst[i];
                        src = divert->udp_src[i];
                        if ((dst && dst == udph->dest) ||
                            (src && src == udph->source)) {
                                ETH_DIVERT_FRAME(skb);
                                return;
                        }
                }
                break;
        }
}