Ejemplo n.º 1
0
/*
 * This is the system call interface. This communicates with
 * the user-level programs. Currently this only supports diskquota
 * calls. Maybe we need to add the process quotas etc. in the future,
 * but we probably should use rlimits for that.
 */
asmlinkage long sys_quotactl(unsigned int cmd, const char *special, qid_t id, caddr_t addr)
{
    uint cmds, type;
    struct super_block *sb = NULL;
    int ret = -EINVAL;

    lock_kernel();
    cmds = cmd >> SUBCMDSHIFT;
    type = cmd & SUBCMDMASK;

#ifdef CONFIG_QIFACE_COMPAT
    if (cmds != Q_V1_GETSTATS && cmds != Q_V2_GETSTATS && IS_ERR(sb = resolve_dev(special))) {
        ret = PTR_ERR(sb);
        sb = NULL;
        goto out;
    }
    if (!NEW_COMMAND(cmds) && !XQM_COMMAND(cmds)) {
        if ((ret = check_compat_quotactl_valid(sb, type, cmds, id)) < 0)
            goto out;
        ret = do_compat_quotactl(sb, type, cmds, id, addr);
        goto out;
    }
#else
    if (IS_ERR(sb = resolve_dev(special))) {
        ret = PTR_ERR(sb);
        sb = NULL;
        goto out;
    }
#endif
    if ((ret = check_quotactl_valid(sb, type, cmds, id)) < 0)
        goto out;
    ret = do_quotactl(sb, type, cmds, id, addr);
out:
    if (sb)
        drop_super(sb);
    unlock_kernel();
    return ret;
}
Ejemplo n.º 2
0
static int ctrl_handle_add_service_msg(struct ctrlmsg *cm, int peer)
{
        struct ctrlmsg_service *cmr = (struct ctrlmsg_service *)cm;
        unsigned int num_res = CTRLMSG_SERVICE_NUM(cmr);
        /* TODO - flags, etc */
        unsigned int i, index = 0;
        int err = 0;

        LOG_DBG("adding %u services, msg size %u\n", 
                num_res, CTRLMSG_SERVICE_LEN(cmr));
        
        for (i = 0; i < num_res; i++) {
                struct net_device *dev = NULL;
                struct service_info *entry = &cmr->service[i];
                unsigned short prefix_bits = SERVICE_ID_MAX_PREFIX_BITS;

                if (entry->type == SERVICE_RULE_FORWARD) {
                        dev = resolve_dev(entry);
                        
                        if (!dev)
                                continue;
                }

                if (entry->srvid_prefix_bits > 0)
                        prefix_bits = entry->srvid_prefix_bits;
         
#if defined(ENABLE_DEBUG)
                {
                        char ipstr[18];
                        LOG_DBG("Adding service id: %s(%u) "
                                "@ address %s, priority %u, weight %u\n", 
                                service_id_to_str(&entry->srvid), 
                                prefix_bits, 
                                inet_ntop(AF_INET, &entry->address,
                                          ipstr, sizeof(ipstr)),
                                entry->priority, entry->weight);
                }
#endif
                err = service_add(&entry->srvid, 
                                  prefix_bits, 
                                  entry->type,
                                  entry->srvid_flags, 
                                  entry->priority, 
                                  entry->weight,
                                  &entry->address, 
                                  sizeof(entry->address),
                                  make_target(dev), GFP_KERNEL);
                if (dev)
                        dev_put(dev);

                if (err > 0) {
                        if (index < i) {
                                /* copy it over */
                                memcpy(&cmr->service[index], 
                                       entry, sizeof(*entry));
                        }
                        index++;
                } else {
                        LOG_ERR("Error adding service %s: err=%d\n", 
                                service_id_to_str(&entry->srvid), err);
                }
        }

        if (index == 0) {
                /* Just return the original request with a return value */
                cm->retval = CTRLMSG_RETVAL_NOENTRY;
        } else {
                /* Return the entries added */
                cm->retval = CTRLMSG_RETVAL_OK;
                cm->len = CTRLMSG_SERVICE_NUM_LEN(index);
        }

        ctrl_sendmsg(cm, peer, GFP_KERNEL);

        return 0;
}
Ejemplo n.º 3
0
static int ctrl_handle_mod_service_msg(struct ctrlmsg *cm, int peer)
{
        struct ctrlmsg_service *cmr = (struct ctrlmsg_service *)cm;
        unsigned int num_res = CTRLMSG_SERVICE_NUM(cmr);
        unsigned int i, index = 0;
        int err = 0;

        if (num_res < 2 || num_res % 2 != 0) {
                LOG_DBG("Not an even number of service infos\n");
                return 0;
        }

        LOG_DBG("modifying %u services\n", num_res / 2);

        for (i = 0; i < num_res; i += 2) {
                struct net_device *dev;
                struct service_info *entry_old = &cmr->service[i];
                struct service_info *entry_new = &cmr->service[i+1];
                unsigned short prefix_bits = SERVICE_ID_MAX_PREFIX_BITS;
                
                if (entry_old->srvid_prefix_bits > 0)
                        prefix_bits = entry_old->srvid_prefix_bits;

#if defined(ENABLE_DEBUG)
                {
                        char buf[18];
                        LOG_DBG("Modifying: %s flags(%i) bits(%i) %s\n", 
                                service_id_to_str(&entry_old->srvid), 
                                entry_old->srvid_flags, 
                                prefix_bits,
                                inet_ntop(AF_INET, &entry_old->address, 
                                          buf, 18));
                }
#endif
                dev = resolve_dev(entry_old);
                
                if (!dev)
                        continue;

                err = service_modify(&entry_old->srvid,
                                     prefix_bits,
                                     SERVICE_RULE_FORWARD,
                                     entry_old->srvid_flags, 
                                     entry_new->priority, 
                                     entry_new->weight, 
                                     &entry_old->address,
                                     sizeof(entry_old->address),
                                     &entry_new->address,
                                     sizeof(entry_new->address), 
                                     make_target(dev));
                if (err > 0) {
                        if (index < i) {
                                /* copy it over */
                                memcpy(&cmr->service[index], 
                                       entry_new, sizeof(*entry_new));
                        }
                        index++;
                } else {
                        LOG_ERR("Could not modify service %s: %i\n", 
                                service_id_to_str(&entry_old->srvid), 
                                err);
                }
                dev_put(dev);
        }
        
        if (index == 0) {
                cm->retval = CTRLMSG_RETVAL_NOENTRY;
        } else {
                cm->retval = CTRLMSG_RETVAL_OK;
                cm->len = CTRLMSG_SERVICE_NUM_LEN(index);
        }
        
        ctrl_sendmsg(cm, peer, GFP_KERNEL);

        return 0;
}