!C99Shell v. 2.0 [PHP 7 Update] [25.02.2019]!

Software: Apache/2.4.18 (Ubuntu). PHP/7.0.33-0ubuntu0.16.04.16 

uname -a: Linux digifus 3.13.0-57-generic #95-Ubuntu SMP Fri Jun 19 09:28:15 UTC 2015 x86_64 

uid=33(www-data) gid=33(www-data) groups=33(www-data) 

Safe-mode: OFF (not secure)

/lib/firmware/carl9170fw/tools/lib/   drwxr-xr-x
Free 9.85 GB of 29.4 GB (33.5%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Feedback    Self remove    Logout    


Viewing file:     carlfw.c (13.35 KB)      -rw-r--r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/*
 * Copyright 2010-2011 Christian Lamparter <chunkeey@googlemail.com>
 *
 * 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 version 2 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <stdlib.h>
#include <stdio.h>
#include <error.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

#include "carlfw.h"

struct carlfw_file {
    char *name;
    size_t len;
    char *data;
};

struct carlfw {
    struct carlfw_file fw;
    struct carlfw_file hdr;

    struct list_head desc_list;
    unsigned int desc_list_entries,
             desc_list_len;
};

#define carlfw_walk_descs(iter, fw)                    \
    list_for_each_entry(iter, &fw->desc_list, h.list)

struct carlfw_list_entry_head {
    struct list_head list;
};

struct carlfw_list_entry {
    struct carlfw_list_entry_head h;
    union {
        struct carl9170fw_desc_head head;
        uint32_t data[0];
        char text[0];
    };
};

static inline struct carlfw_list_entry *carlfw_desc_to_entry(struct carl9170fw_desc_head *head)
{
    return container_of(head, struct carlfw_list_entry, head);
}

static inline struct carl9170fw_desc_head *carlfw_entry_to_desc(struct carlfw_list_entry *entry)
{
    return &entry->head;
}

static void carlfw_entry_unlink(struct carlfw *fw,
    struct carlfw_list_entry *entry)
{
    fw->desc_list_entries--;
    fw->desc_list_len -= le16_to_cpu(entry->head.length);
    list_del(&entry->h.list);
}

static void carlfw_entry_del(struct carlfw *fw,
    struct carlfw_list_entry *entry)
{
    carlfw_entry_unlink(fw, entry);
    free(entry);
}

static struct carlfw_list_entry *carlfw_find_entry(struct carlfw *fw,
                           const uint8_t descid[4],
                           unsigned int len,
                           uint8_t compatible_revision)
{
    struct carlfw_list_entry *iter;

    carlfw_walk_descs(iter, fw) {
        if (carl9170fw_desc_cmp(&iter->head, descid, len,
                     compatible_revision))
            return (void *)iter;
    }

    return NULL;
}

static struct carlfw_list_entry *__carlfw_entry_add_prepare(struct carlfw *fw,
    const struct carl9170fw_desc_head *desc)
{
    struct carlfw_list_entry *tmp;
    unsigned int len;

    len = le16_to_cpu(desc->length);

    if (len < sizeof(struct carl9170fw_desc_head))
        return ERR_PTR(-EINVAL);

    tmp = malloc(sizeof(*tmp) + len);
    if (!tmp)
        return ERR_PTR(-ENOMEM);

    fw->desc_list_entries++;
    fw->desc_list_len += len;

    memcpy(tmp->data, desc, len);
    return tmp;
}

static void __carlfw_release(struct carlfw_file *f)
{
    f->len = 0;
    if (f->name)
        free(f->name);
    f->name = NULL;

    if (f->data)
        free(f->data);
    f->data = NULL;
}

void carlfw_release(struct carlfw *fw)
{
    struct carlfw_list_entry *entry;

    if (!IS_ERR_OR_NULL(fw)) {
        while (!list_empty(&fw->desc_list)) {
            entry = list_entry(fw->desc_list.next,
                       struct carlfw_list_entry, h.list);
            carlfw_entry_del(fw, entry);
        }

        __carlfw_release(&fw->fw);
        __carlfw_release(&fw->hdr);
        free(fw);
    }
}

static int __carlfw_load(struct carlfw_file *file, const char *name, const char *mode)
{
    struct stat file_stat;
    FILE *fh;
    int err;

    fh = fopen(name, mode);
    if (fh == NULL)
        return errno ? -errno : -1;

    err = fstat(fileno(fh), &file_stat);
    if (err)
        return errno ? -errno : -1;

    file->len = file_stat.st_size;
    file->data = malloc(file->len);
    if (file->data == NULL)
        return -ENOMEM;

    err = fread(file->data, file->len, 1, fh);
    if (err != 1)
        return -ferror(fh);

    file->name = strdup(name);
    fclose(fh);

    if (!file->name)
        return -ENOMEM;

    return 0;
}

static void *__carlfw_find_desc(struct carlfw_file *file,
                uint8_t descid[4],
                unsigned int len,
                uint8_t compatible_revision)
{
    int scan = file->len, found = 0;
    struct carl9170fw_desc_head *tmp = NULL;

    while (scan >= 0) {
        if (file->data[scan] == descid[CARL9170FW_MAGIC_SIZE - found - 1])
            found++;
        else
            found = 0;

        if (found == CARL9170FW_MAGIC_SIZE)
            break;

        scan--;
    }

    if (found == CARL9170FW_MAGIC_SIZE) {
        tmp = (void *) &file->data[scan];

        if (!CHECK_HDR_VERSION(tmp, compatible_revision) &&
            (le16_to_cpu(tmp->length) >= len))
            return tmp;
    }

    return NULL;
}

void *carlfw_find_desc(struct carlfw *fw,
               const uint8_t descid[4],
               const unsigned int len,
               const uint8_t compatible_revision)
{
    struct carlfw_list_entry *tmp;

    tmp = carlfw_find_entry(fw, descid, len, compatible_revision);

    return tmp ? carlfw_entry_to_desc(tmp) : NULL;
}

int carlfw_desc_add_tail(struct carlfw *fw,
    const struct carl9170fw_desc_head *desc)
{
    struct carlfw_list_entry *tmp;

    tmp = __carlfw_entry_add_prepare(fw, desc);
    if (IS_ERR(tmp))
        return PTR_ERR(tmp);

    list_add_tail(&tmp->h.list, &fw->desc_list);
    return 0;
}

int carlfw_desc_add(struct carlfw *fw,
            const struct carl9170fw_desc_head *desc,
            struct carl9170fw_desc_head *prev,
            struct carl9170fw_desc_head *next)
{
    struct carlfw_list_entry *tmp;

    tmp = __carlfw_entry_add_prepare(fw, desc);
    if (IS_ERR(tmp))
        return PTR_ERR(tmp);

    list_add(&tmp->h.list, &((carlfw_desc_to_entry(prev))->h.list),
         &((carlfw_desc_to_entry(next))->h.list));
    return 0;
}

int carlfw_desc_add_before(struct carlfw *fw,
               const struct carl9170fw_desc_head *desc,
               struct carl9170fw_desc_head *pos)
{
    struct carl9170fw_desc_head *prev;
    struct carlfw_list_entry *prev_entry;

    prev_entry = carlfw_desc_to_entry(pos);

    prev = carlfw_entry_to_desc((struct carlfw_list_entry *) prev_entry->h.list.prev);

    return carlfw_desc_add(fw, desc, prev, pos);
}

void carlfw_desc_unlink(struct carlfw *fw,
    struct carl9170fw_desc_head *desc)
{
    carlfw_entry_unlink(fw, carlfw_desc_to_entry(desc));
}

void carlfw_desc_del(struct carlfw *fw,
    struct carl9170fw_desc_head *desc)
{
    carlfw_entry_del(fw, carlfw_desc_to_entry(desc));
}

void *carlfw_desc_mod_len(struct carlfw *fw __unused,
    struct carl9170fw_desc_head *desc, size_t len)
{
    struct carlfw_list_entry *obj, tmp;
    int new_len = le16_to_cpu(desc->length) + len;

    if (new_len < (int)sizeof(*desc))
        return ERR_PTR(-EINVAL);

    if (new_len > CARL9170FW_DESC_MAX_LENGTH)
        return ERR_PTR(-E2BIG);

    obj = carlfw_desc_to_entry(desc);

    memcpy(&tmp, obj, sizeof(tmp));
    obj = realloc(obj, new_len + sizeof(struct carlfw_list_entry_head));
    if (obj == NULL)
        return ERR_PTR(-ENOMEM);

    list_replace(&tmp.h.list, &obj->h.list);

    desc = carlfw_entry_to_desc(obj);
    desc->length = le16_to_cpu(new_len);
    fw->desc_list_len += len;

    return desc;
}

void *carlfw_desc_next(struct carlfw *fw,
               struct carl9170fw_desc_head *pos)
{
    struct carlfw_list_entry *entry;

    if (!pos)
        entry = (struct carlfw_list_entry *) &fw->desc_list;
    else
        entry = carlfw_desc_to_entry(pos);

    if (list_at_tail(entry, &fw->desc_list, h.list))
        return NULL;

    entry = (struct carlfw_list_entry *) entry->h.list.next;

    return carlfw_entry_to_desc(entry);
}

static int carlfw_parse_descs(struct carlfw *fw,
                  struct carl9170fw_otus_desc *otus_desc)
{
    const struct carl9170fw_desc_head *iter = NULL;
    int err;

    carl9170fw_for_each_hdr(iter, &otus_desc->head) {
        err = carlfw_desc_add_tail(fw, iter);
        if (err)
            return err;
    }
    /* LAST is added automatically by carlfw_store */

    return err;
}

#if BYTE_ORDER == LITTLE_ENDIAN
#define CRCPOLY_LE 0xedb88320

/* copied from the linux kernel  */
static uint32_t crc32_le(uint32_t crc, unsigned char const *p, size_t len)
{
    int i;
    while (len--) {
        crc ^= *p++;
        for (i = 0; i < 8; i++)
            crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0);
    }
    return crc;
}
#else
#error "this tool does not work with a big endian host yet!"
#endif

static int carlfw_check_crc32s(struct carlfw *fw)
{
    struct carl9170fw_chk_desc *chk_desc;
    struct carlfw_list_entry *iter;
    unsigned int elen;
    uint32_t crc32;

    chk_desc = carlfw_find_desc(fw, (uint8_t *) CHK_MAGIC,
                    sizeof(*chk_desc),
                    CARL9170FW_CHK_DESC_CUR_VER);
    if (!chk_desc)
        return -ENODATA;

    crc32 = crc32_le(~0, (void *) fw->fw.data, fw->fw.len);
    if (crc32 != le32_to_cpu(chk_desc->fw_crc32))
        return -EINVAL;

    carlfw_walk_descs(iter, fw) {
        elen = le16_to_cpu(iter->head.length);

        if (carl9170fw_desc_cmp(&iter->head, (uint8_t *) CHK_MAGIC,
                    sizeof(*chk_desc),
                    CARL9170FW_CHK_DESC_CUR_VER))
            continue;

        crc32 = crc32_le(crc32, (void *) &iter->head, elen);
    }

    if (crc32 != le32_to_cpu(chk_desc->hdr_crc32))
        return -EINVAL;

    return 0;
}

struct carlfw *carlfw_load(const char *basename)
{
    char filename[256];
    struct carlfw *fw;
    struct carl9170fw_otus_desc *otus_desc;
    struct carl9170fw_last_desc *last_desc;
    struct carlfw_file *hdr_file;
    unsigned long fin, diff, off, rem;
    int err;

    fw = calloc(1, sizeof(*fw));
    if (!fw)
        return ERR_PTR(-ENOMEM);

    init_list_head(&fw->desc_list);

    err = __carlfw_load(&fw->fw, basename, "r");
    if (err)
        goto err_out;

    if (fw->hdr.name)
        hdr_file = &fw->hdr;
    else
        hdr_file = &fw->fw;

    otus_desc = __carlfw_find_desc(hdr_file, (uint8_t *) OTUS_MAGIC,
                       sizeof(*otus_desc),
                       CARL9170FW_OTUS_DESC_CUR_VER);
    last_desc = __carlfw_find_desc(hdr_file, (uint8_t *) LAST_MAGIC,
                       sizeof(*last_desc),
                       CARL9170FW_LAST_DESC_CUR_VER);

    if (!otus_desc || !last_desc ||
        (unsigned long) otus_desc > (unsigned long) last_desc) {
        err = -ENODATA;
        goto err_out;
    }

    err = carlfw_parse_descs(fw, otus_desc);
    if (err)
        goto err_out;

    fin = (unsigned long)last_desc + sizeof(*last_desc);
    diff = fin - (unsigned long)otus_desc;
    rem = hdr_file->len - (fin - (unsigned long) hdr_file->data);

    if (rem) {
        off = (unsigned long)otus_desc - (unsigned long)hdr_file->data;
        memmove(&hdr_file->data[off],
            ((uint8_t *)last_desc) + sizeof(*last_desc), rem);
    }

    hdr_file->len -= diff;
    hdr_file->data = realloc(hdr_file->data, hdr_file->len);
    if (!hdr_file->data && hdr_file->len) {
        err = -ENOMEM;
        goto err_out;
    }

    err = carlfw_check_crc32s(fw);
    if (err && err != -ENODATA)
        goto err_out;

    return fw;

err_out:
    carlfw_release(fw);
    return ERR_PTR(err);
}

static int carlfw_apply_checksums(struct carlfw *fw)
{
    struct carlfw_list_entry *iter;
    struct carl9170fw_chk_desc tmp = {
        CARL9170FW_FILL_DESC(CHK_MAGIC, sizeof(tmp),
                      CARL9170FW_CHK_DESC_MIN_VER,
                      CARL9170FW_CHK_DESC_CUR_VER) };
    struct carl9170fw_chk_desc *chk_desc = NULL;
    int err = 0;
    unsigned int len = 0, elen, max_len;
    uint32_t crc32;

    chk_desc = carlfw_find_desc(fw, (uint8_t *) CHK_MAGIC,
                    sizeof(*chk_desc),
                    CARL9170FW_CHK_DESC_CUR_VER);
    if (chk_desc) {
        carlfw_desc_del(fw, &chk_desc->head);
        chk_desc = NULL;
    }

    max_len = fw->desc_list_len;

    crc32 = crc32_le(~0, (void *) fw->fw.data, fw->fw.len);
    tmp.fw_crc32 = cpu_to_le32(crc32);

    /*
     * NOTE:
     *
     * The descriptor checksum is seeded with the firmware's crc32.
     * This neat trick ensures that the driver can check whenever
     * descriptor actually belongs to the firmware, or not.
     */

    carlfw_walk_descs(iter, fw) {
        elen = le16_to_cpu(iter->head.length);

        if (max_len < len + elen)
            return -EMSGSIZE;

        crc32 = crc32_le(crc32, (void *) &iter->head, elen);
        len += elen;
    }

    tmp.hdr_crc32 = cpu_to_le32(crc32);

    err = carlfw_desc_add_tail(fw, &tmp.head);

    return err;
}

int carlfw_store(struct carlfw *fw)
{
    struct carl9170fw_last_desc last_desc = {
        CARL9170FW_FILL_DESC(LAST_MAGIC, sizeof(last_desc),
            CARL9170FW_LAST_DESC_MIN_VER,
            CARL9170FW_LAST_DESC_CUR_VER) };

    struct carlfw_list_entry *iter;
    FILE *fh;
    int err, elen;

    err = carlfw_apply_checksums(fw);
    if (err)
        return err;

    fh = fopen(fw->fw.name, "w");
    if (!fh)
        return -errno;

    err = fwrite(fw->fw.data, fw->fw.len, 1, fh);
    if (err != 1) {
        err = -errno;
        goto close_out;
    }

    if (fw->hdr.name) {
        fclose(fh);

        fh = fopen(fw->hdr.name, "w");
    }

    carlfw_walk_descs(iter, fw) {
        elen = le16_to_cpu(iter->head.length);

        if (elen > CARL9170FW_DESC_MAX_LENGTH) {
            err = -E2BIG;
            goto close_out;
        }

        err = fwrite(iter->data, elen, 1, fh);
        if (err != 1) {
            err = -ferror(fh);
            goto close_out;
        }
    }

    err = fwrite(&last_desc, sizeof(last_desc), 1, fh);
    if (err != 1) {
        err = -ferror(fh);
        goto close_out;
    }

    err = 0;

close_out:
    fclose(fh);
    return err;
}

void *carlfw_mod_tailroom(struct carlfw *fw, ssize_t len)
{
    size_t new_len;
    void *buf;

    new_len = fw->fw.len + len;

    if (!carl9170fw_size_check(new_len))
        return ERR_PTR(-EINVAL);

    buf = realloc(fw->fw.data, new_len);
    if (buf == NULL)
        return ERR_PTR(-ENOMEM);

    fw->fw.len = new_len;
    fw->fw.data = buf;
    return &fw->fw.data[new_len - len];
}

void *carlfw_mod_headroom(struct carlfw *fw, ssize_t len)
{
    size_t new_len;
    void *ptr;

    new_len = fw->fw.len + len;
    if (!carl9170fw_size_check(new_len))
        return ERR_PTR(-EINVAL);

    if (len < 0)
        memmove(fw->fw.data, &fw->fw.data[len], new_len);

    ptr = carlfw_mod_tailroom(fw, len);
    if (IS_ERR_OR_NULL(ptr))
        return ptr;

    if (len > 0)
        memmove(&fw->fw.data[len], &fw->fw.data[0], new_len - len);

    return fw->fw.data;
}

void *carlfw_get_fw(struct carlfw *fw, size_t *len)
{
    *len = fw->fw.len;
    return fw->fw.data;
}

unsigned int carlfw_get_descs_num(struct carlfw *fw)
{
    return fw->desc_list_entries;
}

unsigned int carlfw_get_descs_size(struct carlfw *fw)
{
    return fw->desc_list_len;
}

:: Command execute ::

Enter:
 
Select:
 

:: Search ::
  - regexp 

:: Upload ::
 
[ Read-Only ]

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

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

--[ c99shell v. 2.0 [PHP 7 Update] [25.02.2019] maintained by KaizenLouie | C99Shell Github | Generation time: 0.0062 ]--