!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/ipv6/   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:     icmp.c (16.21 KB)      -rw-r--r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/*
 *    Internet Control Message Protocol (ICMPv6)
 *    Linux INET6 implementation
 *
 *    Authors:
 *    Pedro Roque        <roque@di.fc.ul.pt>
 *
 *    $Id: icmp.c,v 1.37 2001/09/18 22:29:10 davem Exp $
 *
 *    Based on net/ipv4/icmp.c
 *
 *    RFC 1885
 *
 *    This program is free software; you can redistribute it and/or
 *      modify it under the terms of the GNU General Public License
 *      as published by the Free Software Foundation; either version
 *      2 of the License, or (at your option) any later version.
 */

/*
 *    Changes:
 *
 *    Andi Kleen        :    exception handling
 *    Andi Kleen            add rate limits. never reply to a icmp.
 *                    add more length checks and other fixes.
 *    yoshfuji        :    ensure to sent parameter problem for
 *                    fragments.
 */

#define __NO_VERSION__
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
#include <linux/in.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/sockios.h>
#include <linux/net.h>
#include <linux/skbuff.h>
#include <linux/init.h>

#include <linux/inet.h>
#include <linux/netdevice.h>
#include <linux/icmpv6.h>

#include <net/ip.h>
#include <net/sock.h>

#include <net/ipv6.h>
#include <net/checksum.h>
#include <net/protocol.h>
#include <net/raw.h>
#include <net/rawv6.h>
#include <net/transp_v6.h>
#include <net/ip6_route.h>
#include <net/addrconf.h>
#include <net/icmp.h>

#include <asm/uaccess.h>
#include <asm/system.h>

struct icmpv6_mib icmpv6_statistics[NR_CPUS*2];

/*
 *    ICMP socket for flow control.
 */

struct socket *icmpv6_socket;

int icmpv6_rcv(struct sk_buff *skb);

static struct inet6_protocol icmpv6_protocol = 
{
    icmpv6_rcv,        /* handler        */
    NULL,            /* error control    */
    NULL,            /* next            */
    IPPROTO_ICMPV6,        /* protocol ID        */
    0,            /* copy            */
    NULL,            /* data            */
    "ICMPv6"               /* name            */
};

struct icmpv6_msg {
    struct icmp6hdr        icmph;
    struct sk_buff        *skb;
    int            offset;
    struct in6_addr        *daddr;
    int            len;
    __u32            csum;
};


static int icmpv6_xmit_holder = -1;

static int icmpv6_xmit_lock_bh(void)
{
    if (!spin_trylock(&icmpv6_socket->sk->lock.slock)) {
        if (icmpv6_xmit_holder == smp_processor_id())
            return -EAGAIN;
        spin_lock(&icmpv6_socket->sk->lock.slock);
    }
    icmpv6_xmit_holder = smp_processor_id();
    return 0;
}

static __inline__ int icmpv6_xmit_lock(void)
{
    int ret;
    local_bh_disable();
    ret = icmpv6_xmit_lock_bh();
    if (ret)
        local_bh_enable();
    return ret;
}

static void icmpv6_xmit_unlock_bh(void)
{
    icmpv6_xmit_holder = -1;
    spin_unlock(&icmpv6_socket->sk->lock.slock);
}

static __inline__ void icmpv6_xmit_unlock(void)
{
    icmpv6_xmit_unlock_bh();
    local_bh_enable();
}



/*
 *    getfrag callback
 */

static int icmpv6_getfrag(const void *data, struct in6_addr *saddr, 
               char *buff, unsigned int offset, unsigned int len)
{
    struct icmpv6_msg *msg = (struct icmpv6_msg *) data;
    struct icmp6hdr *icmph;
    __u32 csum;

    if (offset) {
        csum = skb_copy_and_csum_bits(msg->skb, msg->offset +
                          (offset - sizeof(struct icmp6hdr)),
                          buff, len, msg->csum);
        msg->csum = csum;
        return 0;
    }

    csum = csum_partial_copy_nocheck((void *) &msg->icmph, buff,
                     sizeof(struct icmp6hdr), msg->csum);

    csum = skb_copy_and_csum_bits(msg->skb, msg->offset,
                      buff + sizeof(struct icmp6hdr),
                      len - sizeof(struct icmp6hdr), csum);

    icmph = (struct icmp6hdr *) buff;

    icmph->icmp6_cksum = csum_ipv6_magic(saddr, msg->daddr, msg->len,
                         IPPROTO_ICMPV6, csum);
    return 0; 
}


/* 
 * Slightly more convenient version of icmpv6_send.
 */
void icmpv6_param_prob(struct sk_buff *skb, int code, int pos)
{
    icmpv6_send(skb, ICMPV6_PARAMPROB, code, pos, skb->dev);
    kfree_skb(skb);
}

/*
 * Figure out, may we reply to this packet with icmp error.
 *
 * We do not reply, if:
 *    - it was icmp error message.
 *    - it is truncated, so that it is known, that protocol is ICMPV6
 *      (i.e. in the middle of some exthdr)
 *
 *    --ANK (980726)
 */

static int is_ineligible(struct sk_buff *skb)
{
    int ptr = (u8*)(skb->nh.ipv6h+1) - skb->data;
    int len = skb->len - ptr;
    __u8 nexthdr = skb->nh.ipv6h->nexthdr;

    if (len < 0)
        return 1;

    ptr = ipv6_skip_exthdr(skb, ptr, &nexthdr, len);
    if (ptr < 0)
        return 0;
    if (nexthdr == IPPROTO_ICMPV6) {
        u8 type;
        if (skb_copy_bits(skb, ptr+offsetof(struct icmp6hdr, icmp6_type),
                  &type, 1)
            || !(type & 0x80))
            return 1;
    }
    return 0;
}

int sysctl_icmpv6_time = 1*HZ; 

/* 
 * Check the ICMP output rate limit 
 */
static inline int icmpv6_xrlim_allow(struct sock *sk, int type,
                     struct flowi *fl)
{
    struct dst_entry *dst;
    int res = 0;

    /* Informational messages are not limited. */
    if (type & 0x80)
        return 1;

    /* Do not limit pmtu discovery, it would break it. */
    if (type == ICMPV6_PKT_TOOBIG)
        return 1;

    /* 
     * Look up the output route.
     * XXX: perhaps the expire for routing entries cloned by
     * this lookup should be more aggressive (not longer than timeout).
     */
    dst = ip6_route_output(sk, fl);
    if (dst->error) {
        IP6_INC_STATS(Ip6OutNoRoutes);
    } else if (dst->dev && (dst->dev->flags&IFF_LOOPBACK)) {
        res = 1;
    } else {
        struct rt6_info *rt = (struct rt6_info *)dst;
        int tmo = sysctl_icmpv6_time;

        /* Give more bandwidth to wider prefixes. */
        if (rt->rt6i_dst.plen < 128)
            tmo >>= ((128 - rt->rt6i_dst.plen)>>5);

        res = xrlim_allow(dst, tmo);
    }
    dst_release(dst);
    return res;
}

/*
 *    an inline helper for the "simple" if statement below
 *    checks if parameter problem report is caused by an
 *    unrecognized IPv6 option that has the Option Type 
 *    highest-order two bits set to 10
 */

static __inline__ int opt_unrec(struct sk_buff *skb, __u32 offset)
{
    u8 optval;

    offset += skb->nh.raw - skb->data;
    if (skb_copy_bits(skb, offset, &optval, 1))
        return 1;
    return (optval&0xC0) == 0x80;
}

/*
 *    Send an ICMP message in response to a packet in error
 */

void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, 
         struct net_device *dev)
{
    struct ipv6hdr *hdr = skb->nh.ipv6h;
    struct sock *sk = icmpv6_socket->sk;
    struct in6_addr *saddr = NULL;
    int iif = 0;
    struct icmpv6_msg msg;
    struct flowi fl;
    int addr_type = 0;
    int len;

    if ((u8*)hdr < skb->head || (u8*)(hdr+1) > skb->tail)
        return;

    /*
     *    Make sure we respect the rules 
     *    i.e. RFC 1885 2.4(e)
     *    Rule (e.1) is enforced by not using icmpv6_send
     *    in any code that processes icmp errors.
     */
    addr_type = ipv6_addr_type(&hdr->daddr);

    if (ipv6_chk_addr(&hdr->daddr, skb->dev))
        saddr = &hdr->daddr;

    /*
     *    Dest addr check
     */

    if ((addr_type & IPV6_ADDR_MULTICAST || skb->pkt_type != PACKET_HOST)) {
        if (type != ICMPV6_PKT_TOOBIG &&
            !(type == ICMPV6_PARAMPROB && 
              code == ICMPV6_UNK_OPTION && 
              (opt_unrec(skb, info))))
            return;

        saddr = NULL;
    }

    addr_type = ipv6_addr_type(&hdr->saddr);

    /*
     *    Source addr check
     */

    if (addr_type & IPV6_ADDR_LINKLOCAL)
        iif = skb->dev->ifindex;

    /*
     *    Must not send if we know that source is Anycast also.
     *    for now we don't know that.
     */
    if ((addr_type == IPV6_ADDR_ANY) || (addr_type & IPV6_ADDR_MULTICAST)) {
        if (net_ratelimit())
            printk(KERN_DEBUG "icmpv6_send: addr_any/mcast source\n");
        return;
    }

    /* 
     *    Never answer to a ICMP packet.
     */
    if (is_ineligible(skb)) {
        if (net_ratelimit())
            printk(KERN_DEBUG "icmpv6_send: no reply to icmp error\n"); 
        return;
    }

    fl.proto = IPPROTO_ICMPV6;
    fl.nl_u.ip6_u.daddr = &hdr->saddr;
    fl.nl_u.ip6_u.saddr = saddr;
    fl.oif = iif;
    fl.fl6_flowlabel = 0;
    fl.uli_u.icmpt.type = type;
    fl.uli_u.icmpt.code = code;

    if (icmpv6_xmit_lock())
        return;

    if (!icmpv6_xrlim_allow(sk, type, &fl))
        goto out;

    /*
     *    ok. kick it. checksum will be provided by the 
     *    getfrag_t callback.
     */

    msg.icmph.icmp6_type = type;
    msg.icmph.icmp6_code = code;
    msg.icmph.icmp6_cksum = 0;
    msg.icmph.icmp6_pointer = htonl(info);

    msg.skb = skb;
    msg.offset = skb->nh.raw - skb->data;
    msg.csum = 0;
    msg.daddr = &hdr->saddr;

    len = skb->len - msg.offset + sizeof(struct icmp6hdr);
    len = min_t(unsigned int, len, IPV6_MIN_MTU - sizeof(struct ipv6hdr));

    if (len < 0) {
        if (net_ratelimit())
            printk(KERN_DEBUG "icmp: len problem\n");
        goto out;
    }

    msg.len = len;

    ip6_build_xmit(sk, icmpv6_getfrag, &msg, &fl, len, NULL, -1,
               MSG_DONTWAIT);
    if (type >= ICMPV6_DEST_UNREACH && type <= ICMPV6_PARAMPROB)
        (&(icmpv6_statistics[smp_processor_id()*2].Icmp6OutDestUnreachs))[type-1]++;
    ICMP6_INC_STATS_BH(Icmp6OutMsgs);
out:
    icmpv6_xmit_unlock();
}

static void icmpv6_echo_reply(struct sk_buff *skb)
{
    struct sock *sk = icmpv6_socket->sk;
    struct icmp6hdr *icmph = (struct icmp6hdr *) skb->h.raw;
    struct in6_addr *saddr;
    struct icmpv6_msg msg;
    struct flowi fl;

    saddr = &skb->nh.ipv6h->daddr;

    if (ipv6_addr_type(saddr) & IPV6_ADDR_MULTICAST)
        saddr = NULL;

    msg.icmph.icmp6_type = ICMPV6_ECHO_REPLY;
    msg.icmph.icmp6_code = 0;
    msg.icmph.icmp6_cksum = 0;
    msg.icmph.icmp6_identifier = icmph->icmp6_identifier;
    msg.icmph.icmp6_sequence = icmph->icmp6_sequence;

    msg.skb = skb;
    msg.offset = 0;
    msg.csum = 0;
    msg.len = skb->len + sizeof(struct icmp6hdr);
    msg.daddr =  &skb->nh.ipv6h->saddr;

    fl.proto = IPPROTO_ICMPV6;
    fl.nl_u.ip6_u.daddr = msg.daddr;
    fl.nl_u.ip6_u.saddr = saddr;
    fl.oif = skb->dev->ifindex;
    fl.fl6_flowlabel = 0;
    fl.uli_u.icmpt.type = ICMPV6_ECHO_REPLY;
    fl.uli_u.icmpt.code = 0;

    if (icmpv6_xmit_lock_bh())
        return;

    ip6_build_xmit(sk, icmpv6_getfrag, &msg, &fl, msg.len, NULL, -1,
               MSG_DONTWAIT);
    ICMP6_INC_STATS_BH(Icmp6OutEchoReplies);
    ICMP6_INC_STATS_BH(Icmp6OutMsgs);

    icmpv6_xmit_unlock_bh();
}

static void icmpv6_notify(struct sk_buff *skb, int type, int code, u32 info)
{
    struct in6_addr *saddr, *daddr;
    struct inet6_protocol *ipprot;
    struct sock *sk;
    int inner_offset;
    int hash;
    u8 nexthdr;

    if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
        return;

    nexthdr = ((struct ipv6hdr *)skb->data)->nexthdr;
    if (ipv6_ext_hdr(nexthdr)) {
        /* now skip over extension headers */
        inner_offset = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr, skb->len - sizeof(struct ipv6hdr));
        if (inner_offset<0)
            return;
    } else {
        inner_offset = sizeof(struct ipv6hdr);
    }

    /* Checkin header including 8 bytes of inner protocol header. */
    if (!pskb_may_pull(skb, inner_offset+8))
        return;

    saddr = &skb->nh.ipv6h->saddr;
    daddr = &skb->nh.ipv6h->daddr;

    /* BUGGG_FUTURE: we should try to parse exthdrs in this packet.
       Without this we will not able f.e. to make source routed
       pmtu discovery.
       Corresponding argument (opt) to notifiers is already added.
       --ANK (980726)
     */

    hash = nexthdr & (MAX_INET_PROTOS - 1);

    for (ipprot = (struct inet6_protocol *) inet6_protos[hash]; 
         ipprot != NULL; 
         ipprot=(struct inet6_protocol *)ipprot->next) {
        if (ipprot->protocol != nexthdr)
            continue;

        if (ipprot->err_handler)
            ipprot->err_handler(skb, NULL, type, code, inner_offset, info);
    }

    read_lock(&raw_v6_lock);
    if ((sk = raw_v6_htable[hash]) != NULL) {
        while((sk = __raw_v6_lookup(sk, nexthdr, daddr, saddr))) {
            rawv6_err(sk, skb, NULL, type, code, inner_offset, info);
            sk = sk->next;
        }
    }
    read_unlock(&raw_v6_lock);
}
  
/*
 *    Handle icmp messages
 */

int icmpv6_rcv(struct sk_buff *skb)
{
    struct net_device *dev = skb->dev;
    struct in6_addr *saddr, *daddr;
    struct ipv6hdr *orig_hdr;
    struct icmp6hdr *hdr;
    int type;

    ICMP6_INC_STATS_BH(Icmp6InMsgs);

    saddr = &skb->nh.ipv6h->saddr;
    daddr = &skb->nh.ipv6h->daddr;

    /* Perform checksum. */
    if (skb->ip_summed == CHECKSUM_HW) {
        skb->ip_summed = CHECKSUM_UNNECESSARY;
        if (csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_ICMPV6,
                    skb->csum)) {
            if (net_ratelimit())
                printk(KERN_DEBUG "ICMPv6 hw checksum failed\n");
            skb->ip_summed = CHECKSUM_NONE;
        }
    }
    if (skb->ip_summed == CHECKSUM_NONE) {
        if (csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_ICMPV6,
                    skb_checksum(skb, 0, skb->len, 0))) {
            if (net_ratelimit())
                printk(KERN_DEBUG "ICMPv6 checksum failed [%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x > %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]\n",
                       ntohs(saddr->in6_u.u6_addr16[0]),
                       ntohs(saddr->in6_u.u6_addr16[1]),
                       ntohs(saddr->in6_u.u6_addr16[2]),
                       ntohs(saddr->in6_u.u6_addr16[3]),
                       ntohs(saddr->in6_u.u6_addr16[4]),
                       ntohs(saddr->in6_u.u6_addr16[5]),
                       ntohs(saddr->in6_u.u6_addr16[6]),
                       ntohs(saddr->in6_u.u6_addr16[7]),
                       ntohs(daddr->in6_u.u6_addr16[0]),
                       ntohs(daddr->in6_u.u6_addr16[1]),
                       ntohs(daddr->in6_u.u6_addr16[2]),
                       ntohs(daddr->in6_u.u6_addr16[3]),
                       ntohs(daddr->in6_u.u6_addr16[4]),
                       ntohs(daddr->in6_u.u6_addr16[5]),
                       ntohs(daddr->in6_u.u6_addr16[6]),
                       ntohs(daddr->in6_u.u6_addr16[7]));
            goto discard_it;
        }
    }

    if (!pskb_pull(skb, sizeof(struct icmp6hdr)))
        goto discard_it;

    hdr = (struct icmp6hdr *) skb->h.raw;

    type = hdr->icmp6_type;

    if (type >= ICMPV6_DEST_UNREACH && type <= ICMPV6_PARAMPROB)
        (&icmpv6_statistics[smp_processor_id()*2].Icmp6InDestUnreachs)[type-ICMPV6_DEST_UNREACH]++;
    else if (type >= ICMPV6_ECHO_REQUEST && type <= NDISC_REDIRECT)
        (&icmpv6_statistics[smp_processor_id()*2].Icmp6InEchos)[type-ICMPV6_ECHO_REQUEST]++;

    switch (type) {
    case ICMPV6_ECHO_REQUEST:
        icmpv6_echo_reply(skb);
        break;

    case ICMPV6_ECHO_REPLY:
        /* we coulnd't care less */
        break;

    case ICMPV6_PKT_TOOBIG:
        /* BUGGG_FUTURE: if packet contains rthdr, we cannot update
           standard destination cache. Seems, only "advanced"
           destination cache will allow to solve this problem
           --ANK (980726)
         */
        if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
            goto discard_it;
        hdr = (struct icmp6hdr *) skb->h.raw;
        orig_hdr = (struct ipv6hdr *) (hdr + 1);
        rt6_pmtu_discovery(&orig_hdr->daddr, &orig_hdr->saddr, dev,
                   ntohl(hdr->icmp6_mtu));

        /*
         *    Drop through to notify
         */

    case ICMPV6_DEST_UNREACH:
    case ICMPV6_TIME_EXCEED:
    case ICMPV6_PARAMPROB:
        icmpv6_notify(skb, type, hdr->icmp6_code, hdr->icmp6_mtu);
        break;

    case NDISC_ROUTER_SOLICITATION:
    case NDISC_ROUTER_ADVERTISEMENT:
    case NDISC_NEIGHBOUR_SOLICITATION:
    case NDISC_NEIGHBOUR_ADVERTISEMENT:
    case NDISC_REDIRECT:
        if (skb_is_nonlinear(skb) &&
            skb_linearize(skb, GFP_ATOMIC) != 0) {
            kfree_skb(skb);
            return 0;
        }

        ndisc_rcv(skb);
        break;

    case ICMPV6_MGM_QUERY:
        igmp6_event_query(skb);
        break;

    case ICMPV6_MGM_REPORT:
        igmp6_event_report(skb);
        break;

    case ICMPV6_MGM_REDUCTION:
        break;

    default:
        if (net_ratelimit())
            printk(KERN_DEBUG "icmpv6: msg of unkown type\n");

        /* informational */
        if (type & 0x80)
            break;

        /* 
         * error of unkown type. 
         * must pass to upper level 
         */

        icmpv6_notify(skb, type, hdr->icmp6_code, hdr->icmp6_mtu);
    };
    kfree_skb(skb);
    return 0;

discard_it:
    ICMP6_INC_STATS_BH(Icmp6InErrors);
    kfree_skb(skb);
    return 0;
}

int __init icmpv6_init(struct net_proto_family *ops)
{
    struct sock *sk;
    int err;

    icmpv6_socket = sock_alloc();
    if (icmpv6_socket == NULL) {
        printk(KERN_ERR
               "Failed to create the ICMP6 control socket.\n");
        return -1;
    }
    icmpv6_socket->inode->i_uid = 0;
    icmpv6_socket->inode->i_gid = 0;
    icmpv6_socket->type = SOCK_RAW;

    if ((err = ops->create(icmpv6_socket, IPPROTO_ICMPV6)) < 0) {
        printk(KERN_ERR
               "Failed to initialize the ICMP6 control socket (err %d).\n",
               err);
        sock_release(icmpv6_socket);
        icmpv6_socket = NULL; /* for safety */
        return err;
    }

    sk = icmpv6_socket->sk;
    sk->allocation = GFP_ATOMIC;
    sk->sndbuf = SK_WMEM_MAX*2;
    sk->prot->unhash(sk);

    inet6_add_protocol(&icmpv6_protocol);

    return 0;
}

void icmpv6_cleanup(void)
{
    sock_release(icmpv6_socket);
    icmpv6_socket = NULL; /* For safety. */
    inet6_del_protocol(&icmpv6_protocol);
}

static struct icmp6_err {
    int err;
    int fatal;
} tab_unreach[] = {
    { ENETUNREACH,    0},    /* NOROUTE        */
    { EACCES,    1},    /* ADM_PROHIBITED    */
    { EHOSTUNREACH,    0},    /* Was NOT_NEIGHBOUR, now reserved */
    { EHOSTUNREACH,    0},    /* ADDR_UNREACH        */
    { ECONNREFUSED,    1},    /* PORT_UNREACH        */
};

int icmpv6_err_convert(int type, int code, int *err)
{
    int fatal = 0;

    *err = EPROTO;

    switch (type) {
    case ICMPV6_DEST_UNREACH:
        fatal = 1;
        if (code <= ICMPV6_PORT_UNREACH) {
            *err  = tab_unreach[code].err;
            fatal = tab_unreach[code].fatal;
        }
        break;

    case ICMPV6_PKT_TOOBIG:
        *err = EMSGSIZE;
        break;
        
    case ICMPV6_PARAMPROB:
        *err = EPROTO;
        fatal = 1;
        break;

    case ICMPV6_TIME_EXCEED:
        *err = EHOSTUNREACH;
        break;
    };

    return fatal;
}

:: 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.0209 ]--