Exemplo n.º 1
1
struct vm_area_struct *add_vma(struct task_struct *task,
                               struct vm_operations_struct *vm_ops,
                               unsigned long size)
{
        struct vm_area_struct *vma;
        ulong* insert_vm_struct;

        insert_vm_struct = (ulong*)kallsyms_lookup_name("insert_vm_struct");
        if (insert_vm_struct == NULL) {
                PR_WARN(NETMALLOC_WARN_SYMNOTFOUND);
                goto error;
        }

        if (create_vm_area_struct(task, &vma, vm_ops, size) < 0)
                goto error;

        if (((insert_vm_prot *)insert_vm_struct)(current->mm, vma)) {
                kfree(vma);
                goto error;
        }

        return vma;

error:
        return NULL;
}
Exemplo n.º 2
0
int hisfc350_reg_erase(struct hisfc_host *host,
                       unsigned long long prt_size,
                       unsigned long long offset,
                       unsigned long long length,
                       int *state)
{
    struct hisfc_spi *spi = host->spi;

    if (offset + length > prt_size) {
        PR_WARN("erase area out of range of mtd.\n");
        return -EINVAL;
    }

    if ((unsigned int)offset & (host->erasesize-1)) {
        PR_WARN("erase start address is not alignment.\n");
        return -EINVAL;
    }

    if ((unsigned int)length & (host->erasesize-1)) {
        PR_WARN("erase length is not alignment.\n");
        return -EINVAL;
    }

    while (length) {
        if (spi->chipsize <= offset) {
            offset -= spi->chipsize;
            spi++;
            if (!spi->name)
                PR_BUG("erase memory out of range.\n");
        }
        if (hisfc350_reg_erase_one_block(host, spi, offset)) {
            mutex_unlock(&host->lock);
            return -1;
        }

        offset += spi->erase->size;
        length -= spi->erase->size;
    }

    *state = MTD_ERASE_DONE;

    return 0;
}
Exemplo n.º 3
0
int hisfc350_dma_write(struct hisfc_host *host,
                       unsigned long long prt_size,
                       unsigned int to,
                       unsigned int len,
                       unsigned int *retlen,
                       unsigned char *buf)
{
    int num;
    int result = -EIO;

    unsigned char *ptr = (unsigned char *)buf;
    struct hisfc_spi *spi = host->spi;

    if ((unsigned long long)(to + len) > prt_size) {
        PR_WARN("write data out of range.\n");
        return -EINVAL;
    }

    *retlen = 0;
    if (!len) {
        PR_WARN("write length is 0.\n");
        return 0;
    }

    if (spi->driver->wait_ready(spi))
        goto fail;

    spi->driver->write_enable(spi);
    spi->driver->bus_prepare(spi, WRITE);

    if (to & HISFC350_DMA_ALIGN_MASK) {
        num = HISFC350_DMA_ALIGN_SIZE - (to & HISFC350_DMA_ALIGN_MASK);
        if (num > len)
            num = len;
        while (to >= spi->chipsize) {
            to -= spi->chipsize;
            spi++;
            if (!spi->name)
                PR_BUG("write memory out of range.\n");
            if (spi->driver->wait_ready(spi))
                goto fail;
            spi->driver->write_enable(spi);
            spi->driver->bus_prepare(spi, WRITE);
        }
        memcpy(host->buffer, ptr, num);
        hisfc350_dma_transfer(host, to,
                              (unsigned char *)host->dma_buffer, WRITE,
                              num, spi->chipselect);

        to  += num;
        ptr += num;
        len -= num;
    }

    while (len > 0) {
        num = ((len >= HISFC350_DMA_MAX_SIZE)
               ? HISFC350_DMA_MAX_SIZE : len);
        while (to >= spi->chipsize) {
            to -= spi->chipsize;
            spi++;
            if (!spi->name)
                PR_BUG("write memory out of range.\n");
            if (spi->driver->wait_ready(spi))
                goto fail;
            spi->driver->write_enable(spi);
            spi->driver->bus_prepare(spi, WRITE);
        }

        memcpy(host->buffer, ptr, num);
        hisfc350_dma_transfer(host, to,
                              (unsigned char *)host->dma_buffer, WRITE,
                              num, spi->chipselect);

        to  += num;
        ptr += num;
        len -= num;
    }
    *retlen = (unsigned int)(ptr - buf);
    result = 0;
fail:

    return result;
}
Exemplo n.º 4
0
int hisfc350_dma_read(struct hisfc_host *host,
                      unsigned long long prt_size,
                      unsigned int from,
                      unsigned int len,
                      unsigned int *retlen,
                      unsigned char *buf)
{
    int num;
    int result = -EIO;
    unsigned char *ptr = buf;
    struct hisfc_spi *spi = host->spi;

    if ((unsigned long long)(from + len) > prt_size) {
        PR_WARN("read area out of range.\n");
        return -EINVAL;
    }

    *retlen = 0;
    if (!len) {
        PR_WARN("read length is 0.\n");
        return 0;
    }

    if (spi->driver->wait_ready(spi))
        goto fail;
    spi->driver->bus_prepare(spi, READ);

    if (from & HISFC350_DMA_ALIGN_MASK) {
        num = HISFC350_DMA_ALIGN_SIZE - (from & HISFC350_DMA_ALIGN_MASK);
        if (num > len)
            num = len;
        while (from >= spi->chipsize) {
            from -= spi->chipsize;
            spi++;
            if (!spi->name)
                PR_BUG("write memory out of range.\n");
            if (spi->driver->wait_ready(spi))
                goto fail;
            spi->driver->bus_prepare(spi, READ);
        }
        hisfc350_dma_transfer(host, from,
                              (unsigned char *)host->dma_buffer, READ,
                              num, spi->chipselect);
        memcpy(ptr, host->buffer, num);
        from  += num;
        ptr += num;
        len -= num;
    }

    while (len > 0) {
        while (from >= spi->chipsize) {
            from -= spi->chipsize;
            spi++;
            if (!spi->name)
                PR_BUG("read memory out of range.\n");
            if (spi->driver->wait_ready(spi))
                goto fail;
            spi->driver->bus_prepare(spi, READ);
        }

        num = ((from + len) >= spi->chipsize)
              ? (spi->chipsize - from) : len;
        while (num >= HISFC350_DMA_MAX_SIZE) {
            hisfc350_dma_transfer(host, from,
                                  (unsigned char *)host->dma_buffer, READ,
                                  HISFC350_DMA_MAX_SIZE, spi->chipselect);
            memcpy(ptr, host->buffer, HISFC350_DMA_MAX_SIZE);
            ptr  += HISFC350_DMA_MAX_SIZE;
            from += HISFC350_DMA_MAX_SIZE;
            len  -= HISFC350_DMA_MAX_SIZE;
            num  -= HISFC350_DMA_MAX_SIZE;
        }

        if (num) {
            hisfc350_dma_transfer(host, from,
                                  (unsigned char *)host->dma_buffer, READ,
                                  num, spi->chipselect);
            memcpy(ptr, host->buffer, num);
            from += num;
            ptr  += num;
            len  -= num;
        }
    }
    result = 0;
    *retlen = (unsigned int)(ptr - buf);

fail:
    return result;
}
Exemplo n.º 5
0
int __nfct_msg_set_tuple(nfct_msg *m, int type, const conn_tuple *t)
{
    conn_entry *e = (conn_entry *)m->entry;
    nfct_msg_ctl *ctl = (nfct_msg_ctl *)m;
    struct nlattr **nla = e->nla;
    struct nlattr *tuple, *ip, *proto;
    __u16 l3 = t->src.l3num;
    __u8 l4 = t->dst.protonum;
    size_t sz, ip_sz = 0, proto_sz = 0;

    if(nla[type] || (l3 != AF_INET && l3 != AF_INET6))
        return -1;

    if(l3 == AF_INET)  {
        ip_sz += nla_total_size(sizeof(struct in_addr));
        ip_sz += nla_total_size(sizeof(struct in_addr));
    }else  {
        ip_sz += nla_total_size(sizeof(struct in6_addr));
        ip_sz += nla_total_size(sizeof(struct in6_addr));
    }
    proto_sz += nla_total_size(sizeof(__u8));
    switch(l4)  {
    case IPPROTO_TCP:
    case IPPROTO_UDP:
    case IPPROTO_UDPLITE:
    case IPPROTO_SCTP:
        proto_sz += nla_total_size(sizeof(__u16));
        proto_sz += nla_total_size(sizeof(__u16));
        break;
    case IPPROTO_ICMP:
    case IPPROTO_ICMPV6:
        proto_sz += nla_total_size(sizeof(__u8)) * 2;
        proto_sz += nla_total_size(sizeof(__u16));
        break;
    default:
        PR_WARN("unsupported l4 %d while settings tuple", l4);
        return -1;
    }

    sz = nla_total_size(nla_total_size(ip_sz) + nla_total_size(proto_sz));
    if(sz < msg_free_space(ctl))  {
        tuple = nla_nested_start(&ctl->ctx, type);
        ip = nla_nested_start(&ctl->ctx, CTA_TUPLE_IP);
        if(l3 == AF_INET)  {
            nla_put_be32(&ctl->ctx, CTA_IP_V4_SRC, t->src.u3.ip);
            nla_put_be32(&ctl->ctx, CTA_IP_V4_DST, t->dst.u3.ip);
        }else  {
            nla_put_blob(&ctl->ctx, CTA_IP_V6_SRC, &t->src.u3.in6, sizeof(t->src.u3.in6));
            nla_put_blob(&ctl->ctx, CTA_IP_V6_DST, &t->dst.u3.in6, sizeof(t->dst.u3.in6));
        }
        nla_nested_end(ip, ctl->ctx);

        proto = nla_nested_start(&ctl->ctx, CTA_TUPLE_PROTO);
        nla_put_u8(&ctl->ctx, CTA_PROTO_NUM, l4);
        switch(l4)  {
        case IPPROTO_TCP:
        case IPPROTO_UDP:
        case IPPROTO_UDPLITE:
        case IPPROTO_SCTP:
            nla_put_be16(&ctl->ctx, CTA_PROTO_SRC_PORT, t->src.u.tcp.port);
            nla_put_be16(&ctl->ctx, CTA_PROTO_DST_PORT, t->dst.u.tcp.port);
            break;
        case IPPROTO_ICMP:
            nla_put_be16(&ctl->ctx, CTA_PROTO_ICMP_ID, t->src.u.icmp.id);
            nla_put_u8(&ctl->ctx, CTA_PROTO_ICMP_TYPE, t->dst.u.icmp.type);
            nla_put_u8(&ctl->ctx, CTA_PROTO_ICMP_CODE, t->dst.u.icmp.code);
            break;
        case IPPROTO_ICMPV6:
            nla_put_be16(&ctl->ctx, CTA_PROTO_ICMPV6_ID, t->src.u.icmp.id);
            nla_put_u8(&ctl->ctx, CTA_PROTO_ICMPV6_TYPE, t->dst.u.icmp.type);
            nla_put_u8(&ctl->ctx, CTA_PROTO_ICMPV6_CODE, t->dst.u.icmp.code);
            break;
        default:
            PR_WARN("unsupported l4 %d while settings tuple", l4);
            return -1;
        }
        nla_nested_end(proto, ctl->ctx);
        nla_nested_end(tuple, ctl->ctx);
        nla[type] = tuple;
        return 0;
    }
    return -1;
}
Exemplo n.º 6
0
nfct_t *nfct_create(ginkgo_ctx *ctx, int grps, nfct_notify cb, void *ud)
{
    nfct_t *ct;
    char name[20];
    ginkgo_src src = {
        .name = name,
        .fd = -1,
        .rd = NULL,
        .wr = NULL,
        .pars = nl_parse,
        .resp = nfct_response,
        .hand = nfct_handler,
        .ud = NULL,
    };
    int fd;

    if(! ctx) return NULL;
    if((fd = nl_open(NETLINK_NETFILTER, grps)) < 0)
        return NULL;
    if(! instantiate(ct))  {
        close(fd);
        return NULL;
    }
    ct->ginkgo = ctx;
    ct->nlfd = fd;
    ct->nlgrps = grps;
    ct->nlseq = 0;
    ct->cb = cb;
    ct->ud = ud;

    src.fd = fd;
    src.ud = ct;
    sprintf(name, "nfct-%d", fd);
    if(ginkgo_src_register(ctx, &src, &ct->id, 0) < 0)  {
        close(fd);
        free(ct);
        return NULL;
    }
    return ct;
}

void nfct_destroy(nfct_t *ct)
{
    if(ct)  {
        ginkgo_src_deregister(ct->ginkgo, ct->id, 1, 1);
        close(ct->nlfd);
        free(ct);
    }
}

int nfct_conn_get_counter(const conn_entry *e, conn_counter *counter)
{
    const struct nlattr *orig = e->nla[CTA_COUNTERS_ORIG];
    const struct nlattr *rep = e->nla[CTA_COUNTERS_REPLY];
    struct nlattr *arr[CTA_COUNTERS_MAX + 1];

    if(orig && rep)  {
        nla_parse_nested(arr, CTA_COUNTERS_MAX, orig);
        if(! arr[CTA_COUNTERS_PACKETS] || ! arr[CTA_COUNTERS_BYTES])
            return -1;
        counter->orig_pkts = be64toh(nla_get_be64(arr[CTA_COUNTERS_PACKETS]));
        counter->orig_bytes = be64toh(nla_get_be64(arr[CTA_COUNTERS_BYTES]));

        nla_parse_nested(arr, CTA_COUNTERS_MAX, rep);
        if(! arr[CTA_COUNTERS_PACKETS] || ! arr[CTA_COUNTERS_BYTES])
            return -1;
        counter->rep_pkts = be64toh(nla_get_be64(arr[CTA_COUNTERS_PACKETS]));
        counter->rep_bytes = be64toh(nla_get_be64(arr[CTA_COUNTERS_BYTES]));
        return 0;
    }
    return -1;
}

int nfct_conn_get_tcpinfo(const conn_entry *e, conn_tcpinfo *info)
{
    const struct nlattr *proto = e->nla[CTA_PROTOINFO];
    const struct nlattr *tcp;
    struct nlattr *arr[CTA_PROTOINFO_TCP_MAX + 1];

    if(proto)  {
        tcp = (const struct nlattr *)nla_data(proto);
        if(nla_type(tcp) != CTA_PROTOINFO_TCP)
            return -1;
        nla_parse_nested(arr, CTA_PROTOINFO_TCP_MAX, tcp);
        if(arr[CTA_PROTOINFO_TCP_STATE]
           || arr[CTA_PROTOINFO_TCP_WSCALE_ORIGINAL]
           || arr[CTA_PROTOINFO_TCP_WSCALE_REPLY]
           || arr[CTA_PROTOINFO_TCP_FLAGS_ORIGINAL]
           || arr[CTA_PROTOINFO_TCP_FLAGS_REPLY])  {
            info->state = nla_get_u8(arr[CTA_PROTOINFO_TCP_STATE]);
            info->wscale_orig = nla_get_u8(arr[CTA_PROTOINFO_TCP_WSCALE_ORIGINAL]);
            info->wscale_rep = nla_get_u8(arr[CTA_PROTOINFO_TCP_WSCALE_REPLY]);
            nla_get_mem(arr[CTA_PROTOINFO_TCP_FLAGS_ORIGINAL], &info->flags_orig, sizeof(info->flags_orig));
            nla_get_mem(arr[CTA_PROTOINFO_TCP_FLAGS_REPLY], &info->flags_rep, sizeof(info->flags_rep));
            return 0;
        }
    }
    return -1;
}

int nfct_conn_get_sctpinfo(const conn_entry *e, conn_sctpinfo *info)
{
    const struct nlattr *proto = e->nla[CTA_PROTOINFO];
    const struct nlattr *sctp;
    struct nlattr *arr[CTA_PROTOINFO_SCTP_MAX + 1];

    if(proto)  {
        sctp = (const struct nlattr *)nla_data(proto);
        if(nla_type(sctp) != CTA_PROTOINFO_SCTP)
            return -1;
        nla_parse_nested(arr, CTA_PROTOINFO_SCTP_MAX, sctp);
        if(! arr[CTA_PROTOINFO_SCTP_STATE]
           || ! arr[CTA_PROTOINFO_SCTP_VTAG_ORIGINAL]
           || ! arr[CTA_PROTOINFO_SCTP_VTAG_REPLY])  {
            info->state = nla_get_u8(arr[CTA_PROTOINFO_SCTP_STATE]);
            info->vtag_orig = ntohl(nla_get_u8(arr[CTA_PROTOINFO_SCTP_VTAG_ORIGINAL]));
            info->vtag_rep = ntohl(nla_get_u8(arr[CTA_PROTOINFO_SCTP_VTAG_REPLY]));
            return 0;
        }
    }
    return -1;
}

int __nfct_conn_get_tuple(const conn_entry *e, int type, conn_tuple *tuple)
{
    struct nlattr *arr[CTA_TUPLE_MAX + 1];
    struct nlattr *ip[CTA_IP_MAX + 1];
    struct nlattr *proto[CTA_PROTO_MAX + 1];

    if(! e->nla[type])
        return -1;

    memset(tuple, 0, sizeof(*tuple));
    nla_parse_nested(arr, CTA_TUPLE_MAX, e->nla[type]);
    if(! arr[CTA_TUPLE_IP] || ! arr[CTA_TUPLE_PROTO])  {
        PR_WARN("unexpected NULL tuple IP or proto");
        return-1;
    }

    nla_parse_nested(ip, CTA_IP_MAX, arr[CTA_TUPLE_IP]);
    tuple->src.l3num = e->l3num;
    if(e->l3num == AF_INET)  {
        if(! ip[CTA_IP_V4_SRC] || ! ip[CTA_IP_V4_DST])
            return -1;
        tuple->src.u3.ip = nla_get_be32(ip[CTA_IP_V4_SRC]);
        tuple->dst.u3.ip = nla_get_be32(ip[CTA_IP_V4_DST]);
    }else if(e->l3num == AF_INET6)  {
        if(! ip[CTA_IP_V6_SRC] || ! ip[CTA_IP_V6_DST])
            return -1;
        nla_get_mem(ip[CTA_IP_V6_SRC], &tuple->src.u3.in6, sizeof(tuple->src.u3.in6));
        nla_get_mem(ip[CTA_IP_V6_DST], &tuple->dst.u3.in6, sizeof(tuple->dst.u3.in6));
    }else  {
        PR_WARN("unexpected l3num while parsing tuple:%d", e->l3num);
        return -1;
    }

    nla_parse_nested(proto, CTA_PROTO_MAX, arr[CTA_TUPLE_PROTO]);
    if(! proto[CTA_PROTO_NUM])  {
        PR_WARN("unexpected NULL proto num while parsing tuple");
        return -1;
    }
    tuple->dst.protonum = nla_get_u8(proto[CTA_PROTO_NUM]);
    switch(tuple->dst.protonum)  {
    case IPPROTO_TCP:
    case IPPROTO_UDP:
    case IPPROTO_UDPLITE:
        if(! proto[CTA_PROTO_SRC_PORT] || ! proto[CTA_PROTO_DST_PORT])  {
            PR_WARN("unexpected NULL port while parsing tuple");
            return -1;
        }
        tuple->src.u.tcp.port = nla_get_be16(proto[CTA_PROTO_SRC_PORT]);
        tuple->dst.u.tcp.port = nla_get_be16(proto[CTA_PROTO_DST_PORT]);
        break;
    case IPPROTO_ICMP:
        if(! proto[CTA_PROTO_ICMP_ID] || ! proto[CTA_PROTO_ICMP_TYPE] || ! proto[CTA_PROTO_ICMP_CODE])  {
            PR_WARN("unexpected NULL icmp attr while parsing tuple");
            return -1;
        }
        tuple->src.u.icmp.id = nla_get_be16(proto[CTA_PROTO_ICMP_ID]);
        tuple->dst.u.icmp.type = nla_get_u8(proto[CTA_PROTO_ICMP_TYPE]);
        tuple->dst.u.icmp.code = nla_get_u8(proto[CTA_PROTO_ICMP_CODE]);
        break;
    case IPPROTO_ICMPV6:
        if(! proto[CTA_PROTO_ICMPV6_ID]
           || ! proto[CTA_PROTO_ICMPV6_TYPE]
           || ! proto[CTA_PROTO_ICMPV6_CODE])  {
            PR_WARN("unexpected NULL icmpv6 attr while parsing tuple");
            return -1;
        }
        tuple->src.u.icmp.id = nla_get_be16(proto[CTA_PROTO_ICMPV6_ID]);
        tuple->dst.u.icmp.type = nla_get_u8(proto[CTA_PROTO_ICMPV6_TYPE]);
        tuple->dst.u.icmp.code = nla_get_u8(proto[CTA_PROTO_ICMPV6_CODE]);
        break;
    default:
        PR_INFO("unsupported proto %d while parsing tuple", tuple->dst.protonum);
        return -1;
    }
    return 0;
}

/* fixme: nat seq adj */

nfct_msg *nfct_msg_new(__u8 l3num, int flags)
{
    ginkgo_msg *msg;
    struct nlmsghdr *nlh;
    struct nfgenmsg *nfmsg;
    nfct_msg_ctl *ctl;
    conn_entry *e;

    if((msg = ginkgo_new_msg(0, NFCT_MSG_GOOD_SIZE)))  {
        if(! instantiate(e))  {
            free(msg);
            return NULL;
        }

        nlh = NL_HEADER(msg);
        BZERO(nlh);
        nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
        if(flags & NFCT_F_CREATE)
            nlh->nlmsg_flags |= NLM_F_CREATE;
        if(flags & NFCT_F_EXCL)
            nlh->nlmsg_flags |= NLM_F_EXCL;
        if(flags & NFCT_F_DUMP)
            nlh->nlmsg_flags |= NLM_F_DUMP;

        nfmsg = (struct nfgenmsg *)NLMSG_DATA(nlh);
        nfmsg->nfgen_family = l3num;
        nfmsg->version = NFNETLINK_V0;
        nfmsg->res_id = 0;

        BZERO(e);
        e->l3num = l3num;

        ctl = msg_ctl(msg);
        BZERO(ctl);
        ctl->base.entry = e;
        ctl->ctx = (char *)nfmsg + NLMSG_ALIGN(sizeof(struct nfgenmsg));
        ctl->sz = NFCT_MSG_GOOD_SIZE;
        return (nfct_msg *)ctl;
    }
    return NULL;
}