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); }
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; }