!C99Shell v. 1.0 pre-release build #13!

Software: Apache/2.0.54 (Unix) mod_perl/1.99_09 Perl/v5.8.0 mod_ssl/2.0.54 OpenSSL/0.9.7l DAV/2 FrontPage/5.0.2.2635 PHP/4.4.0 mod_gzip/2.0.26.1a 

uname -a: Linux snow.he.net 4.4.276-v2-mono-1 #1 SMP Wed Jul 21 11:21:17 PDT 2021 i686 

uid=99(nobody) gid=98(nobody) groups=98(nobody) 

Safe-mode: OFF (not secure)

/usr/src/linux-2.4.18-xfs-1.1/net/core/   drwxr-xr-x
Free 318.37 GB of 458.09 GB (69.5%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Feedback    Self remove    Logout    


Viewing file:     dv.c (11.5 KB)      -rw-r--r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/*
 * INET        An implementation of the TCP/IP protocol suite for the LINUX
 *        operating system.  INET is implemented using the  BSD Socket
 *        interface as the means of communication with the user level.
 *
 *        Generic frame diversion
 *
 * Version:    @(#)eth.c    0.41    09/09/2000
 *
 * Authors:    
 *         Benoit LOCHER:    initial integration within the kernel with support for ethernet
 *         Dave Miller:    improvement on the code (correctness, performance and source files)
 *
 */
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/socket.h>
#include <linux/in.h>
#include <linux/inet.h>
#include <linux/ip.h>
#include <linux/udp.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <net/dst.h>
#include <net/arp.h>
#include <net/sock.h>
#include <net/ipv6.h>
#include <net/ip.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/checksum.h>
#include <linux/divert.h>
#include <linux/sockios.h>

const char sysctl_divert_version[32]="0.46";    /* Current version */

int __init dv_init(void)
{
    printk(KERN_INFO "NET4: Frame Diverter %s\n", sysctl_divert_version);
    return 0;
}

/*
 * Allocate a divert_blk for a device. This must be an ethernet nic.
 */
int alloc_divert_blk(struct net_device *dev)
{
    int alloc_size = (sizeof(struct divert_blk) + 3) & ~3;

    if (dev->type == ARPHRD_ETHER) {
        printk(KERN_DEBUG "divert: allocating divert_blk for %s\n",
               dev->name);

        dev->divert = (struct divert_blk *)
            kmalloc(alloc_size, GFP_KERNEL);
        if (dev->divert == NULL) {
            printk(KERN_DEBUG "divert: unable to allocate divert_blk for %s\n",
                   dev->name);
            return -ENOMEM;
        } else {
            memset(dev->divert, 0, sizeof(struct divert_blk));
        }
        dev_hold(dev);
    } else {
        printk(KERN_DEBUG "divert: not allocating divert_blk for non-ethernet device %s\n",
               dev->name);

        dev->divert = NULL;
    }
    return 0;


/*
 * Free a divert_blk allocated by the above function, if it was 
 * allocated on that device.
 */
void free_divert_blk(struct net_device *dev)
{
    if (dev->divert) {
        kfree(dev->divert);
        dev->divert=NULL;
        dev_put(dev);
        printk(KERN_DEBUG "divert: freeing divert_blk for %s\n",
               dev->name);
    } else {
        printk(KERN_DEBUG "divert: no divert_blk to free, %s not ethernet\n",
               dev->name);
    }
}

/*
 * Adds a tcp/udp (source or dest) port to an array
 */
int add_port(u16 ports[], u16 port)
{
    int i;

    if (port == 0)
        return -EINVAL;

    /* Storing directly in network format for performance,
     * thanks Dave :)
     */
    port = htons(port);

    for (i = 0; i < MAX_DIVERT_PORTS; i++) {
        if (ports[i] == port)
            return -EALREADY;
    }
    
    for (i = 0; i < MAX_DIVERT_PORTS; i++) {
        if (ports[i] == 0) {
            ports[i] = port;
            return 0;
        }
    }

    return -ENOBUFS;
}

/*
 * Removes a port from an array tcp/udp (source or dest)
 */
int remove_port(u16 ports[], u16 port)
{
    int i;

    if (port == 0)
        return -EINVAL;
    
    /* Storing directly in network format for performance,
     * thanks Dave !
     */
    port = htons(port);

    for (i = 0; i < MAX_DIVERT_PORTS; i++) {
        if (ports[i] == port) {
            ports[i] = 0;
            return 0;
        }
    }

    return -EINVAL;
}

/* Some basic sanity checks on the arguments passed to divert_ioctl() */
int check_args(struct divert_cf *div_cf, struct net_device **dev)
{
    char devname[32];
    int ret;

    if (dev == NULL)
        return -EFAULT;
    
    /* GETVERSION: all other args are unused */
    if (div_cf->cmd == DIVCMD_GETVERSION)
        return 0;
    
    /* Network device index should reasonably be between 0 and 1000 :) */
    if (div_cf->dev_index < 0 || div_cf->dev_index > 1000) 
        return -EINVAL;
            
    /* Let's try to find the ifname */
    sprintf(devname, "eth%d", div_cf->dev_index);
    *dev = dev_get_by_name(devname);
    
    /* dev should NOT be null */
    if (*dev == NULL)
        return -EINVAL;

    ret = 0;

    /* user issuing the ioctl must be a super one :) */
    if (!capable(CAP_SYS_ADMIN)) {
        ret = -EPERM;
        goto out;
    }

    /* Device must have a divert_blk member NOT null */
    if ((*dev)->divert == NULL)
        ret = -EINVAL;
out:
    dev_put(*dev);
    return ret;
}

/*
 * control function of the diverter
 */
#define    DVDBG(a)    \
    printk(KERN_DEBUG "divert_ioctl() line %d %s\n", __LINE__, (a))

int divert_ioctl(unsigned int cmd, struct divert_cf *arg)
{
    struct divert_cf    div_cf;
    struct divert_blk    *div_blk;
    struct net_device    *dev;
    int            ret;

    switch (cmd) {
    case SIOCGIFDIVERT:
        DVDBG("SIOCGIFDIVERT, copy_from_user");
        if (copy_from_user(&div_cf, arg, sizeof(struct divert_cf)))
            return -EFAULT;
        DVDBG("before check_args");
        ret = check_args(&div_cf, &dev);
        if (ret)
            return ret;
        DVDBG("after checkargs");
        div_blk = dev->divert;
            
        DVDBG("befre switch()");
        switch (div_cf.cmd) {
        case DIVCMD_GETSTATUS:
            /* Now, just give the user the raw divert block
             * for him to play with :)
             */
            if (copy_to_user(div_cf.arg1.ptr, dev->divert,
                     sizeof(struct divert_blk)))
                return -EFAULT;
            break;

        case DIVCMD_GETVERSION:
            DVDBG("GETVERSION: checking ptr");
            if (div_cf.arg1.ptr == NULL)
                return -EINVAL;
            DVDBG("GETVERSION: copying data to userland");
            if (copy_to_user(div_cf.arg1.ptr,
                     sysctl_divert_version, 32))
                return -EFAULT;
            DVDBG("GETVERSION: data copied");
            break;

        default:
            return -EINVAL;
        };

        break;

    case SIOCSIFDIVERT:
        if (copy_from_user(&div_cf, arg, sizeof(struct divert_cf)))
            return -EFAULT;

        ret = check_args(&div_cf, &dev);
        if (ret)
            return ret;

        div_blk = dev->divert;

        switch(div_cf.cmd) {
        case DIVCMD_RESET:
            div_blk->divert = 0;
            div_blk->protos = DIVERT_PROTO_NONE;
            memset(div_blk->tcp_dst, 0,
                   MAX_DIVERT_PORTS * sizeof(u16));
            memset(div_blk->tcp_src, 0,
                   MAX_DIVERT_PORTS * sizeof(u16));
            memset(div_blk->udp_dst, 0,
                   MAX_DIVERT_PORTS * sizeof(u16));
            memset(div_blk->udp_src, 0,
                   MAX_DIVERT_PORTS * sizeof(u16));
            return 0;
                
        case DIVCMD_DIVERT:
            switch(div_cf.arg1.int32) {
            case DIVARG1_ENABLE:
                if (div_blk->divert)
                    return -EALREADY;
                div_blk->divert = 1;
                break;

            case DIVARG1_DISABLE:
                if (!div_blk->divert)
                    return -EALREADY;
                div_blk->divert = 0;
                break;

            default:
                return -EINVAL;
            };

            break;

        case DIVCMD_IP:
            switch(div_cf.arg1.int32) {
            case DIVARG1_ENABLE:
                if (div_blk->protos & DIVERT_PROTO_IP)
                    return -EALREADY;
                div_blk->protos |= DIVERT_PROTO_IP;
                break;

            case DIVARG1_DISABLE:
                if (!(div_blk->protos & DIVERT_PROTO_IP))
                    return -EALREADY;
                div_blk->protos &= ~DIVERT_PROTO_IP;
                break;

            default:
                return -EINVAL;
            };

            break;

        case DIVCMD_TCP:
            switch(div_cf.arg1.int32) {
            case DIVARG1_ENABLE:
                if (div_blk->protos & DIVERT_PROTO_TCP)
                    return -EALREADY;
                div_blk->protos |= DIVERT_PROTO_TCP;
                break;

            case DIVARG1_DISABLE:
                if (!(div_blk->protos & DIVERT_PROTO_TCP))
                    return -EALREADY;
                div_blk->protos &= ~DIVERT_PROTO_TCP;
                break;

            default:
                return -EINVAL;
            };

            break;

        case DIVCMD_TCPDST:
            switch(div_cf.arg1.int32) {
            case DIVARG1_ADD:
                return add_port(div_blk->tcp_dst,
                        div_cf.arg2.uint16);
                
            case DIVARG1_REMOVE:
                return remove_port(div_blk->tcp_dst,
                           div_cf.arg2.uint16);

            default:
                return -EINVAL;
            };

            break;

        case DIVCMD_TCPSRC:
            switch(div_cf.arg1.int32) {
            case DIVARG1_ADD:
                return add_port(div_blk->tcp_src,
                        div_cf.arg2.uint16);

            case DIVARG1_REMOVE:
                return remove_port(div_blk->tcp_src,
                           div_cf.arg2.uint16);

            default:
                return -EINVAL;
            };

            break;

        case DIVCMD_UDP:
            switch(div_cf.arg1.int32) {
            case DIVARG1_ENABLE:
                if (div_blk->protos & DIVERT_PROTO_UDP)
                    return -EALREADY;
                div_blk->protos |= DIVERT_PROTO_UDP;
                break;

            case DIVARG1_DISABLE:
                if (!(div_blk->protos & DIVERT_PROTO_UDP))
                    return -EALREADY;
                div_blk->protos &= ~DIVERT_PROTO_UDP;
                break;

            default:
                return -EINVAL;
            };

            break;

        case DIVCMD_UDPDST:
            switch(div_cf.arg1.int32) {
            case DIVARG1_ADD:
                return add_port(div_blk->udp_dst,
                        div_cf.arg2.uint16);

            case DIVARG1_REMOVE:
                return remove_port(div_blk->udp_dst,
                           div_cf.arg2.uint16);

            default:
                return -EINVAL;
            };

            break;

        case DIVCMD_UDPSRC:
            switch(div_cf.arg1.int32) {
            case DIVARG1_ADD:
                return add_port(div_blk->udp_src,
                        div_cf.arg2.uint16);

            case DIVARG1_REMOVE:
                return remove_port(div_blk->udp_src,
                           div_cf.arg2.uint16);

            default:
                return -EINVAL;
            };

            break;

        case DIVCMD_ICMP:
            switch(div_cf.arg1.int32) {
            case DIVARG1_ENABLE:
                if (div_blk->protos & DIVERT_PROTO_ICMP)
                    return -EALREADY;
                div_blk->protos |= DIVERT_PROTO_ICMP;
                break;

            case DIVARG1_DISABLE:
                if (!(div_blk->protos & DIVERT_PROTO_ICMP))
                    return -EALREADY;
                div_blk->protos &= ~DIVERT_PROTO_ICMP;
                break;

            default:
                return -EINVAL;
            };

            break;

        default:
            return -EINVAL;
        };

        break;

    default:
        return -EINVAL;
    };

    return 0;
}


/*
 * Check if packet should have its dest mac address set to the box itself
 * for diversion
 */

#define    ETH_DIVERT_FRAME(skb) \
    memcpy(skb->mac.ethernet, skb->dev->dev_addr, ETH_ALEN); \
    skb->pkt_type=PACKET_HOST
        
void divert_frame(struct sk_buff *skb)
{
    struct ethhdr            *eth = skb->mac.ethernet;
    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;
    };

    return;
}


:: Command execute ::

Enter:
 
Select:
 

:: Search ::
  - regexp 

:: Upload ::
 
[ Read-Only ]

:: Make Dir ::
 
[ Read-Only ]
:: Make File ::
 
[ Read-Only ]

:: Go Dir ::
 
:: Go File ::
 

--[ c99shell v. 1.0 pre-release build #13 powered by Captain Crunch Security Team | http://ccteam.ru | Generation time: 0.022 ]--