Ejemplo n.º 1
0
static int
__pfq_join_group(int gid, int id, unsigned long class_mask, int policy)
{
        struct pfq_group * g = pfq_get_group(gid);
        unsigned long tmp = 0;
        unsigned long bit;

        if (!g) {
                pr_devel("[PFQ] get_group: invalid group id %d!\n", gid);
                return -EINVAL;
        }

	/* if this group is unused, initializes it */

        if (!g->pid)
                __pfq_group_init(gid);

        if (!__pfq_group_access(gid, id, policy, true)) {
                pr_devel("[PFQ] gid:%d is not joinable with policy %d\n", gid, policy);
                return -1;
        }

        pfq_bitwise_foreach(class_mask, bit,
        {
                 int class = pfq_ctz(bit);
                 tmp = atomic_long_read(&g->sock_mask[class]);
                 tmp |= 1L << id;
                 atomic_long_set(&g->sock_mask[class], tmp);
        })

	if (g->owner == -1) {
Ejemplo n.º 2
0
static int
__pfq_join_group(int gid, int id, unsigned long class_mask, int policy)
{
        unsigned long tmp = 0;
        unsigned long bit;

        if (!pfq_groups[gid].pid) {
                __pfq_group_ctor(gid);
        }

        if (!__pfq_group_access(gid, id, policy, true)) {
                pr_devel("[PFQ] gid:%d is not joinable with policy %d\n", gid, policy);
                return -1;
        }

        pfq_bitwise_foreach(class_mask, bit)
        {
                int class = pfq_ctz(bit);
                tmp = atomic_long_read(&pfq_groups[gid].sock_mask[class]);
                tmp |= 1L << id;
                atomic_long_set(&pfq_groups[gid].sock_mask[class], tmp);
        }
Ejemplo n.º 3
0
int pfq_getsockopt(struct socket *sock,
                int level, int optname,
                char __user * optval, int __user * optlen)
{
        struct pfq_sock *so = pfq_sk(sock->sk);
        struct pfq_rx_opt * ro;
        struct pfq_tx_opt * to;
        int len;

        if (so == NULL)
                return -EFAULT;

        ro = &so->rx_opt;
        to = &so->tx_opt;

        if (get_user(len, optlen))
                return -EFAULT;
        if (len < 0)
                return -EINVAL;

        switch(optname)
        {

        case Q_SO_GROUP_JOIN:
        {
                struct pfq_group_join group;

                if (len != sizeof(group))
                        return -EINVAL;

                if (copy_from_user(&group, optval, sizeof(group)))
                        return -EFAULT;

                if (group.class_mask == 0) {
                        pr_devel("[PFQ|%d] join error: bad class_mask(%lx)!\n", so->id, group.class_mask);
                        return -EINVAL;
                }

                if (group.gid == Q_ANY_GROUP) {

                        group.gid = pfq_join_free_group(so->id, group.class_mask, group.policy);
                        if (group.gid < 0)
                                return -EFAULT;
                        if (copy_to_user(optval, &group, len))
                                return -EFAULT;
                }
                else {
                        CHECK_GROUP(so->id, group.gid, "group join");

                        if (pfq_join_group(group.gid, so->id, group.class_mask, group.policy) < 0) {
                                pr_devel("[PFQ|%d] join error: permission denied (gid:%d)!\n", so->id, group.gid);
                                return -EACCES;
                        }
                }

                pr_devel("[PFQ|%d] join -> gid:%d class_mask:%lx\n", so->id, group.gid, group.class_mask);
        } break;

        case Q_SO_GET_ID:
        {
                if (len != sizeof(so->id))
                        return -EINVAL;
                if (copy_to_user(optval, &so->id, sizeof(so->id)))
                        return -EFAULT;
        } break;

        case Q_SO_GET_STATUS:
        {
                int enabled;
                if (len != sizeof(int))
                        return -EINVAL;

                enabled = so->mem_addr == NULL ? 0 : 1;

                if (copy_to_user(optval, &enabled, sizeof(enabled)))
                        return -EFAULT;

        } break;

        case Q_SO_GET_STATS:
        {
                struct pfq_stats stat;
                if (len != sizeof(struct pfq_stats))
                        return -EINVAL;

                stat.recv = sparse_read(&ro->stat.recv);
                stat.lost = sparse_read(&ro->stat.lost);
                stat.drop = sparse_read(&ro->stat.drop);

                stat.sent = sparse_read(&to->stat.sent);
                stat.disc = sparse_read(&to->stat.disc);

                if (copy_to_user(optval, &stat, sizeof(stat)))
                        return -EFAULT;
        } break;

        case Q_SO_GET_RX_TSTAMP:
        {
                if (len != sizeof(ro->tstamp))
                        return -EINVAL;
                if (copy_to_user(optval, &ro->tstamp, sizeof(ro->tstamp)))
                        return -EFAULT;
        } break;

        case Q_SO_GET_QUEUE_MEM:
        {
                if (len != sizeof(so->mem_size))
                        return -EINVAL;

                if (copy_to_user(optval, &so->mem_size, sizeof(so->mem_size)))
                        return -EFAULT;
        } break;

        case Q_SO_GET_RX_CAPLEN:
        {
                if (len != sizeof(ro->caplen))
                        return -EINVAL;
                if (copy_to_user(optval, &ro->caplen, sizeof(ro->caplen)))
                        return -EFAULT;
        } break;

        case Q_SO_GET_TX_MAXLEN:
        {
                if (len != sizeof(to->maxlen))
                        return -EINVAL;
                if (copy_to_user(optval, &to->maxlen, sizeof(to->maxlen)))
                        return -EFAULT;
        } break;

        case Q_SO_GET_RX_SLOTS:
        {
                if (len != sizeof(ro->size))
                        return -EINVAL;
                if (copy_to_user(optval, &ro->size, sizeof(ro->size)))
                        return -EFAULT;
        } break;

        case Q_SO_GET_TX_SLOTS:
        {
                if (len != sizeof(to->size))
                        return -EINVAL;
                if (copy_to_user(optval, &to->size, sizeof(to->size)))
                        return -EFAULT;
        } break;

        case Q_SO_GET_GROUPS:
        {
                unsigned long grps;
                if(len != sizeof(unsigned long))
                        return -EINVAL;
                grps = pfq_get_groups(so->id);
                if (copy_to_user(optval, &grps, sizeof(grps)))
                        return -EFAULT;
        } break;

        case Q_SO_GET_GROUP_STATS:
        {
                struct pfq_group *g;
                struct pfq_stats stat;
                int gid;

                if (len != sizeof(stat))
                        return -EINVAL;

                if (copy_from_user(&stat, optval, sizeof(stat)))
                        return -EFAULT;

                gid = (int)stat.recv;

                CHECK_GROUP(so->id, gid, "group stat");

                g = pfq_get_group(gid);
                if (!g) {
                        pr_devel("[PFQ|%d] group error: invalid group id %d!\n", so->id, gid);
                        return -EFAULT;
                }

                /* check whether the group is joinable.. */

                if (!__pfq_group_access(gid, so->id, Q_POLICY_GROUP_UNDEFINED, false)) {
                        pr_devel("[PFQ|%d] group stats error: permission denied (gid:%d)!\n", so->id, gid);
                        return -EACCES;
                }

                stat.recv = sparse_read(&g->recv);
                stat.lost = sparse_read(&g->lost);
                stat.drop = sparse_read(&g->drop);

                stat.sent = 0;
                stat.disc = 0;

                if (copy_to_user(optval, &stat, sizeof(stat)))
                        return -EFAULT;
        } break;

        case Q_SO_GET_GROUP_COUNTERS:
        {
                struct pfq_group *g;
                struct pfq_counters cs;
                int i, gid;

                if (len != sizeof(cs))
                        return -EINVAL;

                if (copy_from_user(&cs, optval, sizeof(cs)))
                        return -EFAULT;

                gid = (int)cs.counter[0];

                CHECK_GROUP(so->id, gid, "group stat");

                g = pfq_get_group(gid);
                if (!g) {
                        pr_devel("[PFQ|%d] group error: invalid group id %d!\n", so->id, gid);
                        return -EFAULT;
                }

                /* check whether the group is joinable.. */

                if (!__pfq_group_access(gid, so->id, Q_POLICY_GROUP_UNDEFINED, false)) {
                        pr_devel("[PFQ|%d] group error: permission denied (gid:%d)!\n", so->id, gid);
                        return -EACCES;
                }

                for(i = 0; i < Q_MAX_COUNTERS; i++)
                {
                        cs.counter[i] = sparse_read(&g->ctx.counter[i]);
                }

                if (copy_to_user(optval, &cs, sizeof(cs)))
                        return -EFAULT;
        } break;

        default:
                return -EFAULT;
        }

        return 0;
}