Exemplo n.º 1
0
static int local_service_generic(struct hostctrl *hc, int type,
                                 const struct service_id *srvid,
                                 unsigned short prefix_bits,
                                 unsigned int priority,
                                 unsigned int weight,
                                 const struct in_addr *ipaddr)
{
    struct {
        struct ctrlmsg_service cm;
        struct service_info service;
    } req;

    if (!srvid)
        return -1;

    memset(&req, 0, sizeof(req));
    req.cm.cmh.type = type;
    req.cm.cmh.xid = ++hc->xid;
    req.cm.cmh.len = CTRLMSG_SERVICE_NUM_LEN(1);
    req.cm.service[0].srvid_prefix_bits =
        (prefix_bits > SERVICE_ID_MAX_PREFIX_BITS) ?
        0 : prefix_bits;
    req.cm.service[0].priority = priority;
    req.cm.service[0].weight = weight;
    memcpy(&req.cm.service[0].srvid, srvid, sizeof(*srvid));

    if (ipaddr)
        memcpy(&req.cm.service[0].address, ipaddr, sizeof(*ipaddr));

    req.cm.service[0].if_index = -1;

    /* strncpy(req.cm.ifname, ifname, IFNAMSIZ - 1); */

    LOG_DBG("op=%d prefix_bits=%u len=%u sizeof(req)=%zu %zu %s\n",
            type, req.cm.service[0].srvid_prefix_bits,
            CTRLMSG_SERVICE_LEN(&req.cm), sizeof(req),
            CTRLMSG_SERVICE_NUM(&req.cm),
            service_id_to_str(&req.cm.service[0].srvid));

    return message_channel_send(hc->mc, &req.cm, req.cm.cmh.len);
}
Exemplo n.º 2
0
static int local_service_modify(struct hostctrl *hc,
                                const struct service_id *srvid,
                                unsigned short prefix_bits,
                                unsigned int priority,
                                unsigned int weight,
                                const struct in_addr *old_ip,
                                const struct in_addr *new_ip)
{
    struct {
        struct ctrlmsg_service cm;
        struct service_info service[2];
    } req;

    if (!srvid || !old_ip)
        return -1;

    memset(&req, 0, sizeof(req));
    req.cm.cmh.type = CTRLMSG_TYPE_MOD_SERVICE;
    req.cm.cmh.len = CTRLMSG_SERVICE_NUM_LEN(2);
    req.cm.cmh.xid = ++hc->xid;
    req.service[0].srvid_prefix_bits =
        (prefix_bits > SERVICE_ID_MAX_PREFIX_BITS) ?
        0 : prefix_bits;
    req.service[0].priority = priority;
    req.service[0].weight = weight;
    memcpy(&req.service[0].srvid, srvid, sizeof(*srvid));
    memcpy(&req.service[0].address, old_ip, sizeof(*old_ip));

    req.service[0].if_index = -1;
    req.service[1].if_index = -1;

    if (!new_ip)
        memcpy(&req.service[1].address, old_ip, sizeof(*old_ip));
    else
        memcpy(&req.service[1].address, new_ip, sizeof(*new_ip));

    /* strncpy(cm.ifname, ifname, IFNAMSIZ - 1); */

    return message_channel_send(hc->mc, &req.cm, req.cm.cmh.len);
}
Exemplo n.º 3
0
static int ctrl_handle_get_service_msg(struct ctrlmsg *cm, int peer)
{
        struct ctrlmsg_service *cmg = (struct ctrlmsg_service *)cm;
        struct service_entry *se;
        struct service_iter iter;
        unsigned short prefix_bits = SERVICE_ID_MAX_PREFIX_BITS;
        struct target *t;

        LOG_DBG("getting service: %s\n",
                service_id_to_str(&cmg->service[0].srvid));

        if (cmg->service[0].srvid_prefix_bits > 0)
                prefix_bits = cmg->service[0].srvid_prefix_bits;

        se = service_find(&cmg->service[0].srvid, 
                          prefix_bits);

        if (se) {
                struct ctrlmsg_service *cres;
                size_t size = CTRLMSG_SERVICE_NUM_LEN(se->count);
                int i = 0;
                          
                cres = kmalloc(size, GFP_KERNEL);

                if (!cres) {
                        service_entry_put(se);
                        cm->retval = CTRLMSG_RETVAL_ERROR;
                        ctrl_sendmsg(cm, peer, GFP_KERNEL);
                        return -ENOMEM;
                }

                memset(cres, 0, size);
                cres->cmh.type = CTRLMSG_TYPE_GET_SERVICE;
                cres->cmh.len = size;
                cres->cmh.xid = cm->xid;
                cres->xid = cmg->xid;

                memset(&iter, 0, sizeof(iter));
                service_iter_init(&iter, se, SERVICE_ITER_FORWARD);

                while ((t = service_iter_next(&iter)) != NULL) {
                        struct service_info *entry = &cres->service[i++];

                        service_get_id(se, &entry->srvid);
                        memcpy(&entry->address, 
                               t->dst, t->dstlen);
                        
                        entry->srvid_prefix_bits = service_get_prefix_bits(se);
                        entry->srvid_flags = service_iter_get_flags(&iter);
                        entry->weight = t->weight;
                        entry->priority = service_iter_get_priority(&iter);
                        
#if defined(ENABLE_DEBUG)
                        {
                                char buf[18];
                                LOG_DBG("Get %s %s priority=%u weight=%u\n", 
                                service_id_to_str(&entry->srvid), 
                                        inet_ntop(AF_INET, &t->dst, 
                                                  buf, 18),
                                        entry->priority,
                                        entry->weight);
                        }
#endif
                        
                }

                service_iter_destroy(&iter);
                service_entry_put(se);

                if (i == 0)
                        cres->cmh.retval = CTRLMSG_RETVAL_NOENTRY;
                else
                        cres->cmh.retval = CTRLMSG_RETVAL_OK;

                ctrl_sendmsg(&cres->cmh, peer, GFP_KERNEL);
                kfree(cres);
                LOG_DBG("Service %s matched %u entries. msg_len=%u\n",
                        service_id_to_str(&cmg->service[0].srvid),
                        se->count, cres->cmh.len);
        } else {
                cmg->service[0].srvid_flags = SVSF_INVALID;
                cmg->cmh.retval = CTRLMSG_RETVAL_NOENTRY;
                ctrl_sendmsg(&cmg->cmh, peer, GFP_KERNEL);
                LOG_DBG("Service %s not found\n",
                        service_id_to_str(&cmg->service[0].srvid));
        }

        return 0;
}
Exemplo n.º 4
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;
}
Exemplo n.º 5
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;
}