예제 #1
0
/* !DO NOT ALTER FUNCTION SIGNATURE! */
int callback_ofc_capable_switch_ofc_id (void ** data, XMLDIFF_OP op, xmlNodePtr node, struct nc_err** error)
{
	nc_verb_verbose("%s: data=%p, op=%d\n", __PRETTY_FUNCTION__, data, op);
	assert(0 == strcmp(node->name, "id"));
	assert(node);
	assert(node->doc);
	assert(node->children);

	if ((XMLDIFF_ADD|XMLDIFF_MOD) & op) {

		xmlChar* text = xmlNodeListGetString(node->doc, node->children, 1);

		nc_verb_verbose("got string: \n%s\n", text);

		if (ofc_state.capable_switch_id) {
			free(ofc_state.capable_switch_id);
		}
		ofc_state.capable_switch_id = strdup(text);
		xmlFree(text);
	} else if (XMLDIFF_REM & op) {
		if (ofc_state.capable_switch_id) {
			free(ofc_state.capable_switch_id);
			ofc_state.capable_switch_id = NULL;
		}
	} else {
		// todo anything else?
		nc_verb_verbose("%s: unsupported operation %u\n", __PRETTY_FUNCTION__, op);
		assert(0);
		return EXIT_FAILURE;
	}


	return EXIT_SUCCESS;
}
예제 #2
0
/* !DO NOT ALTER FUNCTION SIGNATURE! */
int callback_ofc_capable_switch_xdpd_mgmt_cross_connections_xdpd_mgmt_cross_connection (void ** data, XMLDIFF_OP op, xmlNodePtr node, struct nc_err** error)
{
	nc_verb_verbose("%s: data=%p, op=%d\n", __PRETTY_FUNCTION__, data, op);
	print_element_names(node, 0);

	uint64_t dpid_1 = 0;
	uint64_t dpid_2 = 0;
	uint64_t port_no1 = 0;
	uint64_t port_no2 = 0;

	if (XMLDIFF_ADD & op) {
		int i=0;
		xmlNodePtr lsi;
		for (lsi = node->children->next; NULL != lsi; lsi = lsi->next, ++i) {
			assert(xmlStrEqual(lsi->name, BAD_CAST "switch"));

			// resolve dpid
			char buf[255];
			xmlStrPrintf(buf, sizeof(buf), "/ofc:capable-switch/ofc:logical-switches/ofc:switch[ofc:id='%s']", XML_GET_CONTENT(lsi->children->children));
			xmlXPathObjectPtr xpath_obj_ptr = get_node(lsi->doc, namespace_mapping, buf);
			assert(xpath_obj_ptr);
			assert(xpath_obj_ptr->nodesetval);


			// there can only be one lsi with this id
			if (1 == xpath_obj_ptr->nodesetval->nodeNr) {

				xmlNodePtr dpid_node = find_element(BAD_CAST "datapath-id", xpath_obj_ptr->nodesetval->nodeTab[0]->children);
				assert(dpid_node);

				if (0 == i) {
					dpid_1 = parse_dpid(XML_GET_CONTENT(dpid_node->children));
				} else {
					dpid_2 = parse_dpid(XML_GET_CONTENT(dpid_node->children));
				}

			} else {
				// otherwise something is really screwed
				assert(0);
			}
			xmlXPathFreeObject(xpath_obj_ptr);

			xmlNodePtr requested_portnum = find_element(BAD_CAST "requested-of-port-number", lsi->children);
			if (NULL != requested_portnum) {

				if (0 == i) {
					port_no1 = strtoul(XML_GET_CONTENT(requested_portnum->children), NULL, 10);
				} else {
					port_no2 = strtoul(XML_GET_CONTENT(requested_portnum->children), NULL, 10);
				}
			}
		}

		nc_verb_verbose("dpid_1 = %lx, dpid_2 = %lx\n", dpid_1, dpid_2);
		lsi_cross_connect(ofc_state.xmp_client_handle, dpid_1, port_no1, dpid_2, port_no2);
	}

	return EXIT_SUCCESS;
}
예제 #3
0
int
ofcds_init(void *UNUSED(data))
{
    if (!ovsdb_path) {
        /* default path */
        asprintf(&ovsdb_path, "unix:%s/db.sock", ovs_rundir());
    }
    if (ofc_init(ovsdb_path) == false) {
        return EXIT_FAILURE;
    }

    /* hack - OVS calls openlog() and rewrites the syslog settings of the
     * ofc-server. So we have to rewrite syslog settings back by another
     * openlog() call */
    if (ofc_daemonize) {
        openlog("ofc-server", LOG_PID, LOG_DAEMON);
    } else {
        openlog("ofc-server", LOG_PID | LOG_PERROR, LOG_DAEMON);
    }

    /* get startup data */
    gds_startup = xmlReadFile(OFC_DATADIR "/startup.xml", NULL, XML_READ_OPT);
    /* check that there are some data, if not, continue with empty startup */
    if (!xmlDocGetRootElement(gds_startup)) {
        xmlFreeDoc(gds_startup);
        gds_startup = NULL;
    }

    nc_verb_verbose("OF-CONFIG datastore initialized.");
    return EXIT_SUCCESS;
}
예제 #4
0
/* !DO NOT ALTER FUNCTION SIGNATURE! */
int callback_ofc_capable_switch_ofc_logical_switches (void ** data, XMLDIFF_OP op, xmlNodePtr node, struct nc_err** error)
{
	nc_verb_verbose("%s: data=%p, op=%d\n", __PRETTY_FUNCTION__, data, op);
	print_element_names(node, 0);

	int rv = EXIT_SUCCESS;
	if (NULL != node->children) {

		assert(ofc_state.lsi_list);
		assert(XMLDIFF_CHAIN & op);

		if ((XMLDIFF_ADD|XMLDIFF_REM|XMLDIFF_MOD|XMLDIFF_CHAIN) & op) {

			struct lsi *current_lsi;
			while ( (current_lsi = list_next(ofc_state.lsi_list)) ) {
				handle_ports(current_lsi->res.port_list_del);
			}

			while ( (current_lsi = list_pop_head(ofc_state.lsi_list)) ) {
				handle_ports(current_lsi->res.port_list_add);
				lsi_cleanup(current_lsi);
			}

		} else {
			nc_verb_error("unsupported op");
			assert(0);
		}

		list_delete(ofc_state.lsi_list);
		ofc_state.lsi_list = NULL;
	}

	return rv;
}
예제 #5
0
파일: server.c 프로젝트: JimBrv/of-config
/* Signal handler - controls main loop */
void
signal_handler(int sig)
{
    nc_verb_verbose("Signal %d received.", sig);

    switch (sig) {
    case SIGINT:
    case SIGTERM:
    case SIGQUIT:
    case SIGABRT:
    case SIGKILL:
        if (mainloop == 0) {
            /* first attempt */
            mainloop = 1;
        } else {
            /* second attempt */
            nc_verb_error("Hey! I need some time, be patient next time!");
            exit(EXIT_FAILURE);
        }
        break;
    default:
        nc_verb_error("Exiting on signal: %d", sig);
        exit(EXIT_FAILURE);
        break;
    }
}
예제 #6
0
/* !DO NOT ALTER FUNCTION SIGNATURE! */
int callback_ofc_capable_switch_ofc_logical_switches_ofc_switch_ofc_controllers_ofc_controller (void ** data, XMLDIFF_OP op, xmlNodePtr node, struct nc_err** error)
{
	nc_verb_verbose("%s: data=%p, op=%d\n", __PRETTY_FUNCTION__, data, op);
	print_element_names(node, 0);

	if (NULL == *data) {
		*data = calloc(1, sizeof(struct lsi));
		assert(*data);
	}

	if ((XMLDIFF_ADD) & op) {
		if (NULL == LSI(data)->controller_list_add) {
			LSI(data)->controller_list_add = list_new();
			assert(LSI(data)->controller_list_add);
		}

		list_append_data(LSI(data)->controller_list_add, __data);
		__data = NULL;

	} else if ((XMLDIFF_REM) & op) {
		if (NULL == LSI(data)->controller_list_del) {
			LSI(data)->controller_list_del = list_new();
			assert(LSI(data)->controller_list_del);
		}

		list_append_data(LSI(data)->controller_list_del, __data);
		__data = NULL;
	} else {
		nc_verb_error("not implemented");
		assert(0);
	}

	return EXIT_SUCCESS;
}
/**
 * @brief Free all resources allocated on plugin runtime and prepare plugin for removal.
 */
void netopeer_transapi_close_tls(void) {
	struct np_trusted_cert* cert, *del_cert;
	struct np_ctn_item* item, *del_item;

	nc_verb_verbose("Netopeer TLS cleanup.");

	free(netopeer_options.tls_opts->server_cert);
	free(netopeer_options.tls_opts->server_key);
	for (cert = netopeer_options.tls_opts->trusted_certs; cert != NULL;) {
		del_cert = cert;
		cert = cert->next;
		free(del_cert->cert);
		free(del_cert);
	}
	free(netopeer_options.tls_opts->crl_dir);
	for (item = netopeer_options.tls_opts->ctn_map; item != NULL;) {
		del_item = item;
		item = item->next;
		free(del_item->fingerprint);
		free(del_item->name);
		free(del_item);
	}

	pthread_mutex_destroy(&netopeer_options.tls_opts->tls_ctx_lock);
	pthread_mutex_destroy(&netopeer_options.tls_opts->crl_dir_lock);
	pthread_mutex_destroy(&netopeer_options.tls_opts->ctn_map_lock);
	free(netopeer_options.tls_opts);
	netopeer_options.tls_opts = NULL;
}
예제 #8
0
static void
handle_ports(void *list)
{
	if (NULL != list) {

		// handle ports
		struct port *p;
		while ((p = list_pop_head(list))) {

			nc_verb_verbose("dpid=%lx port %s with op=%u\n", p->dpid, p->resource_id, p->op);
			if (ADD == p->op) {
				// attach port
				port_attach(ofc_state.xmp_client_handle, p->dpid, p->resource_id);
			} else if (DELETE == p->op) {
				// detach port
				port_detach(ofc_state.xmp_client_handle, p->dpid, p->resource_id);
			} else {
				assert(0);
			}

			xmlFree(p->resource_id);
			free(p);
		}
	}
}
예제 #9
0
/* !DO NOT ALTER FUNCTION SIGNATURE! */
int callback_ofc_capable_switch_ofc_resources_ofc_port_ofc_configuration_ofc_admin_state (void ** data, XMLDIFF_OP op, xmlNodePtr node, struct nc_err** error)
{
	nc_verb_verbose("%s: data=%p, op=%d\n", __PRETTY_FUNCTION__, data, op);
	print_element_names(node, 0);

	int rv = EXIT_SUCCESS;
	int down = 0;	// default is up

	if ((XMLDIFF_ADD|XMLDIFF_MOD) & op) {

		if (xmlStrEqual(XML_GET_CONTENT(node->children), BAD_CAST "down")) {
			down = 1;
		}

		// sanity check... if the content is not "down", it has to be "up"
		assert(down || xmlStrEqual(XML_GET_CONTENT(node->children), BAD_CAST "up"));

		// currently the resource-id is the port name (even if the name is not set
		xmlNodePtr tmp = find_element(BAD_CAST "resource-id",  node->parent->parent->children);
		assert(tmp);

		if (down) {
			// set interface down
			nc_verb_verbose("set interface %s down\n", tmp->children->content);
			if (port_disable(ofc_state.xmp_client_handle, tmp->children->content)) {
				rv = EXIT_FAILURE;
			}

		} else {
			// set interface up
			nc_verb_verbose("set interface %s up\n", tmp->children->content);
			if (port_enable(ofc_state.xmp_client_handle, tmp->children->content)) {
				rv = EXIT_FAILURE;
			}
		}

	} else if (XMLDIFF_REM & op) {
		// setting interface up
	} else {
		nc_verb_error("unsupported op");
		assert(0);
	}


	return rv;
}
예제 #10
0
/* !DO NOT ALTER FUNCTION SIGNATURE! */
int callback_ofc_capable_switch (void ** data, XMLDIFF_OP op, xmlNodePtr node, struct nc_err** error)
{
	nc_verb_verbose("%s: data=%p, op=%d\n", __PRETTY_FUNCTION__, data, op);

	xmlSaveFormatFileEnc("-", node->doc, "UTF-8", 1);

	return EXIT_SUCCESS;
}
예제 #11
0
/**
 * @brief Initialize plugin after loaded and before any other functions are called.

 * This function should not apply any configuration data to the controlled device. If no
 * running is returned (it stays *NULL), complete startup configuration is consequently
 * applied via module callbacks. When a running configuration is returned, libnetconf
 * then applies (via module's callbacks) only the startup configuration data that
 * differ from the returned running configuration data.

 * Please note, that copying startup data to the running is performed only after the
 * libnetconf's system-wide close - see nc_close() function documentation for more
 * information.

 * @param[out] running	Current configuration of managed device.

 * @return EXIT_SUCCESS or EXIT_FAILURE
 */
int transapi_init(xmlDocPtr * running)
{
	assert(running);
	assert(NULL == *running);

	memset(&ofc_state, 0, sizeof(struct of_config__status));
	ofc_state.xmp_client_handle = new_xmp_client();

	// since we currently cannot query the switch_id we set it manually
	ofc_state.capable_switch_id = strdup("xdpd-switch");

	// create running config as following:
	//	   +--rw capable-switch
	//	      +--rw id                      inet:uri
	//	      +--rw configuration-points
	//	      +--rw resources
	//	      +--rw logical-switches

	nc_verb_verbose("create running config");

	*running = xmlNewDoc(BAD_CAST "1.0");
	assert(*running);
	xmlNodePtr root = xmlNewNode(NULL, BAD_CAST "capable-switch");
	assert(root);
	xmlDocSetRootElement(*running, root);
	xmlNsPtr ns = xmlNewNs(root, BAD_CAST namespace_mapping[0].href, NULL);
	assert(ns);
	xmlSetNs(root, ns);

	xmlNodePtr id = xmlNewChild(root, ns, BAD_CAST "id", BAD_CAST ofc_state.capable_switch_id);
	assert(id);
	xmlNodePtr config_points = xmlNewChild(root, ns, BAD_CAST "configuration-points", NULL);
	assert(config_points);
	xmlNodePtr resources = xmlNewChild(root, ns, BAD_CAST "resources", NULL);
	assert(resources);
	get_resources(ofc_state.xmp_client_handle, resources);
	xmlNodePtr lsis = xmlNewChild(root, ns, BAD_CAST "logical-switches", NULL);
	assert(lsis);
	get_lsi_config(ofc_state.xmp_client_handle, lsis);


	xmlSaveFormatFileEnc("-", *running, "UTF-8", 1);

	nc_verb_verbose("init done\n");
	return EXIT_SUCCESS;
}
int netopeer_transapi_init_tls(void) {

	/* there is no default configuration, but what the heck */
	nc_verb_verbose("Setting the default configuration for the cfgnetopeer module TLS...");

	netopeer_options.tls_opts = calloc(1, sizeof(struct np_options_tls));
	pthread_mutex_init(&netopeer_options.tls_opts->tls_ctx_lock, NULL);
	pthread_mutex_init(&netopeer_options.tls_opts->crl_dir_lock, NULL);
	pthread_mutex_init(&netopeer_options.tls_opts->ctn_map_lock, NULL);

	return EXIT_SUCCESS;
}
예제 #13
0
/**
 * @brief Free all resources allocated on plugin runtime and prepare plugin for removal.
 */
void transapi_close(void)
{
	delete_xmp_client(ofc_state.xmp_client_handle);
	ofc_state.xmp_client_handle = NULL;

	if(ofc_state.capable_switch_id) {
		free(ofc_state.capable_switch_id);
		ofc_state.capable_switch_id = NULL;
	}

	nc_verb_verbose("closed\n");
	return;
}
예제 #14
0
int
ofcds_unlock(void *UNUSED(data), NC_DATASTORE target, const char *session_id,
             struct nc_err **error)
{
    int *locked;
    char **sid;

    switch (target) {
    case NC_DATASTORE_RUNNING:
        locked = &(locks.running);
        sid = &(locks.running_sid);
        break;
    case NC_DATASTORE_STARTUP:
        locked = &(locks.startup);
        sid = &(locks.startup_sid);
        break;
    case NC_DATASTORE_CANDIDATE:
        locked = &(locks.cand);
        sid = &(locks.cand_sid);
        break;
    default:
        /* handled by libnetconf */
        return EXIT_FAILURE;
    }

    if (*locked) {
        if (strcmp(*sid, session_id) == 0) {
            /* correct request, unlock */
            *locked = 0;
            free(*sid);
            *sid = NULL;
            nc_verb_verbose("OFC datastore %d unlocked by %s.", target,
                            session_id);
        } else {
            /* locked by another session */
            *error = nc_err_new(NC_ERR_LOCK_DENIED);
            nc_err_set(*error, NC_ERR_PARAM_INFO_SID, *sid);
            nc_err_set(*error, NC_ERR_PARAM_MSG,
                       "Target datastore is locked by another session.");
            return EXIT_FAILURE;
        }
    } else {
        /* not locked */
        *error = nc_err_new(NC_ERR_OP_FAILED);
        nc_err_set(*error, NC_ERR_PARAM_MSG,
                   "Target datastore is not locked.");
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}
예제 #15
0
/**
 * @brief Free all resources allocated on plugin runtime and prepare plugin for removal.
 */
void netopeer_transapi_close(void) {
#ifdef NP_TLS
	if (ncds_feature_isenabled("cfgnetopeer", "tls")) {
		netopeer_transapi_close_tls();
	}
#endif
#ifdef NP_SSH
	if (ncds_feature_isenabled("cfgnetopeer", "ssh")) {
		netopeer_transapi_close_ssh();
	}
#endif

	nc_verb_verbose("Netopeer cleanup.");

	while (netopeer_options.modules) {
		module_disable(netopeer_options.modules, 1);
	}
}
예제 #16
0
/* !DO NOT ALTER FUNCTION SIGNATURE! */
int callback_ofc_capable_switch_ofc_logical_switches_ofc_switch_ofc_controllers_ofc_controller_ofc_ip_address (void ** data, XMLDIFF_OP op, xmlNodePtr node, struct nc_err** error)
{
	nc_verb_verbose("%s: data=%p, op=%d\n", __PRETTY_FUNCTION__, data, op);
	assert(__data);

	if ((XMLDIFF_ADD) & op) {

		// fixme handle zone in address (see http://www.netconfcentral.org/modules/ietf-inet-types)
		CONTROLLER(__data)->ip_domain = parse_ip_address(XML_GET_CONTENT(node->children), &CONTROLLER(__data)->ip);

	} else if ((XMLDIFF_REM) & op) {
	} else {
		nc_verb_error("not implemented");
		assert(0);
	}

	return EXIT_SUCCESS;
}
예제 #17
0
/* !DO NOT ALTER FUNCTION SIGNATURE! */
int callback_ofc_capable_switch_ofc_logical_switches_ofc_switch_ofc_controllers_ofc_controller_ofc_port (void ** data, XMLDIFF_OP op, xmlNodePtr node, struct nc_err** error)
{
	nc_verb_verbose("%s: data=%p, op=%d\n", __PRETTY_FUNCTION__, data, op);

	assert(__data);

	if ((XMLDIFF_ADD) & op) {

		CONTROLLER(__data)->port = strtoul(XML_GET_CONTENT(node->children), NULL, 10);

	} else if ((XMLDIFF_REM) & op) {
	} else {
		nc_verb_error("not implemented");
		assert(0);
	}

	return EXIT_SUCCESS;
}
예제 #18
0
/* !DO NOT ALTER FUNCTION SIGNATURE! */
int callback_ofc_capable_switch_ofc_logical_switches_ofc_switch_ofc_controllers_ofc_controller_ofc_id (void ** data, XMLDIFF_OP op, xmlNodePtr node, struct nc_err** error)
{
	nc_verb_verbose("%s: data=%p, op=%d\n", __PRETTY_FUNCTION__, data, op);

	assert(NULL == __data);

	if ((XMLDIFF_ADD|XMLDIFF_REM) & op) {
		__data = calloc(1, sizeof(struct controller));

		CONTROLLER(__data)->id = strdup(XML_GET_CONTENT(node->children));
		assert(CONTROLLER(__data)->id);

	} else {
		nc_verb_error("not implemented");
		assert(0);
	}

	return EXIT_SUCCESS;
}
/**
 * @brief Free all resources allocated on plugin runtime and prepare plugin for removal.
 */
void netopeer_transapi_close_ssh(void) {
	struct np_auth_key* key, *del_key;

	nc_verb_verbose("Netopeer SSH cleanup.");

	free(netopeer_options.ssh_opts->rsa_key);
	free(netopeer_options.ssh_opts->dsa_key);
	for (key = netopeer_options.ssh_opts->client_auth_keys; key != NULL;) {
		del_key = key;
		key = key->next;
		free(del_key->path);
		free(del_key->username);
		free(del_key);
	}

	pthread_mutex_destroy(&netopeer_options.ssh_opts->client_keys_lock);
	free(netopeer_options.ssh_opts);
	netopeer_options.ssh_opts = NULL;
}
예제 #20
0
int
ofcds_lock(void *UNUSED(data), NC_DATASTORE target, const char *session_id,
           struct nc_err **error)
{
    int *locked;
    char **sid;

    switch (target) {
    case NC_DATASTORE_RUNNING:
        locked = &(locks.running);
        sid = &(locks.running_sid);
        break;
    case NC_DATASTORE_STARTUP:
        locked = &(locks.startup);
        sid = &(locks.startup_sid);
        break;
    case NC_DATASTORE_CANDIDATE:
        locked = &(locks.cand);
        sid = &(locks.cand_sid);
        break;
    default:
        /* handled by libnetconf */
        return EXIT_FAILURE;
    }

    if (*locked) {
        /* datastore is already locked */
        *error = nc_err_new(NC_ERR_LOCK_DENIED);
        nc_err_set(*error, NC_ERR_PARAM_INFO_SID, *sid);
        return EXIT_FAILURE;
    } else {
        /* remember the lock */
        *locked = 1;
        *sid = strdup(session_id);
        nc_verb_verbose("OFC datastore %d locked by %s.", target, session_id);
    }

    return EXIT_SUCCESS;
}
예제 #21
0
/* !DO NOT ALTER FUNCTION SIGNATURE! */
int callback_ofc_capable_switch_ofc_logical_switches_ofc_switch_ofc_datapath_id (void ** data, XMLDIFF_OP op, xmlNodePtr node, struct nc_err** error)
{
	nc_verb_verbose("%s: data=%p, op=%d\n", __PRETTY_FUNCTION__, data, op);
	assert(NULL == __data);
	if (NULL == *data) {
		*data = calloc(1, sizeof(struct lsi));
		assert(*data);
	}

	if ((XMLDIFF_ADD|XMLDIFF_REM) & op) {
		xmlChar* text = xmlNodeListGetString(node->doc, node->children, 1);
		uint64_t dpid = parse_dpid(text);
		xmlFree(text);

		LSI(data)->dpid = dpid;
	} else {
		// todo add operation to modify dpid
		nc_verb_error("not implemented");
		assert(0);
	}

	return EXIT_SUCCESS;
}
예제 #22
0
/**
 * @brief Retrieve state data from device and return them as XML document
 *
 * @param model	Device data model. libxml2 xmlDocPtr.
 * @param running	Running datastore content. libxml2 xmlDocPtr.
 * @param[out] err  Double pointer to error structure. Fill error when some occurs.
 * @return State data as libxml2 xmlDocPtr or NULL in case of error.
 */
xmlDocPtr get_state_data (xmlDocPtr model, xmlDocPtr running, struct nc_err **err)
{
	nc_verb_verbose("get_state_data\n");

	nc_verb_verbose("erropt=%u\n", erropt);

	xmlDocPtr state;
	xmlNodePtr root;
	xmlNsPtr ns;

	state = xmlNewDoc(BAD_CAST "1.0");
	root = xmlNewDocNode(state, NULL, BAD_CAST "capable-switch", NULL);
	xmlDocSetRootElement(state, root);
	ns = xmlNewNs(root, BAD_CAST "urn:onf:of111:config:yang", NULL);
	xmlSetNs(root, ns);

	// state that should be queried here
	// ### base
	// #/ofc:capable-switch/ofc:config-version
	xmlNewChild(root, ns, BAD_CAST "config-version", BAD_CAST "1.1.1");
//	// ### configuration points
//	// ### Resources
//
	xmlNodePtr resources = xmlNewChild(root, NULL, BAD_CAST "resources", NULL);

	// #/ofc:capable-switch/ofc:resources/ofc:port/ofc:number
	// #/ofc:capable-switch/ofc:resources/ofc:port/ofc:current-rate
	// #/ofc:capable-switch/ofc:resources/ofc:port/ofc:max-rate
	// #/ofc:capable-switch/ofc:resources/ofc:port/ofc:state
	// #/ofc:capable-switch/ofc:resources/ofc:port/ofc:state/ofc:oper-state
	// #/ofc:capable-switch/ofc:resources/ofc:port/ofc:state/ofc:blocked
	// #/ofc:capable-switch/ofc:resources/ofc:port/ofc:state/ofc:live
	// #/ofc:capable-switch/ofc:resources/ofc:port/ofc:features/ofc:current
	// #/ofc:capable-switch/ofc:resources/ofc:port/ofc:features/ofc:current/ofc:rate
	// #/ofc:capable-switch/ofc:resources/ofc:port/ofc:features/ofc:current/ofc:auto-negotiate
	// #/ofc:capable-switch/ofc:resources/ofc:port/ofc:features/ofc:current/ofc:medium
	// #/ofc:capable-switch/ofc:resources/ofc:port/ofc:features/ofc:current/ofc:pause
	// #/ofc:capable-switch/ofc:resources/ofc:port/ofc:features/ofc:supported
	// #/ofc:capable-switch/ofc:resources/ofc:port/ofc:features/ofc:supported/ofc:rate
	// #/ofc:capable-switch/ofc:resources/ofc:port/ofc:features/ofc:supported/ofc:auto-negotiate
	// #/ofc:capable-switch/ofc:resources/ofc:port/ofc:features/ofc:supported/ofc:medium
	// #/ofc:capable-switch/ofc:resources/ofc:port/ofc:features/ofc:supported/ofc:pause
	// #/ofc:capable-switch/ofc:resources/ofc:port/ofc:features/ofc:advertised-peer
	// #/ofc:capable-switch/ofc:resources/ofc:port/ofc:features/ofc:advertised-peer/ofc:rate
	// #/ofc:capable-switch/ofc:resources/ofc:port/ofc:features/ofc:advertised-peer/ofc:auto-negotiate
	// #/ofc:capable-switch/ofc:resources/ofc:port/ofc:features/ofc:advertised-peer/ofc:medium
	// #/ofc:capable-switch/ofc:resources/ofc:port/ofc:features/ofc:advertised-peer/ofc:pause
	get_port_info(ofc_state.xmp_client_handle, resources, running);

	xmlNodePtr lsis = xmlNewChild(root, NULL, BAD_CAST "logical-switches", NULL);
	// ### LSIs
	// #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:capabilities
	// #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:capabilities/ofc:max-buffered-packets
	// #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:capabilities/ofc:max-tables
	// #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:capabilities/ofc:max-ports
	// #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:capabilities/ofc:flow-statistics
	// #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:capabilities/ofc:table-statistics
	// #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:capabilities/ofc:port-statistics
	// #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:capabilities/ofc:group-statistics
	// #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:capabilities/ofc:queue-statistics
	// #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:capabilities/ofc:reassemble-ip-fragments
	// #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:capabilities/ofc:block-looping-ports
	// #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:capabilities/ofc:reserved-port-types
	// #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:capabilities/ofc:reserved-port-types/ofc:type
	// #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:capabilities/ofc:group-types
	// #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:capabilities/ofc:group-types/ofc:type
	// #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:capabilities/ofc:group-capabilities
	// #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:capabilities/ofc:group-capabilities/ofc:capability
	// #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:capabilities/ofc:action-types
	// #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:capabilities/ofc:action-types/ofc:type
	// #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:capabilities/ofc:instruction-types
	// #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:capabilities/ofc:instruction-types/ofc:type
	// #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:controllers/ofc:controller/ofc:state
	// #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:controllers/ofc:controller/ofc:state/ofc:connection-state
	// #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:controllers/ofc:controller/ofc:state/ofc:current-version
	// #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:controllers/ofc:controller/ofc:state/ofc:supported-versions
	// #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:controllers/ofc:controller/ofc:state/ofc:local-ip-address-in-use
	// #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:controllers/ofc:controller/ofc:state/ofc:local-port-in-use
	get_lsi_info(ofc_state.xmp_client_handle, lsis, running);

	return state;
}
예제 #23
0
/* !DO NOT ALTER FUNCTION SIGNATURE! */
int callback_ofc_capable_switch_ofc_logical_switches_ofc_switch_ofc_resources_ofc_port (void ** data, XMLDIFF_OP op, xmlNodePtr node, struct nc_err** error)
{
	nc_verb_verbose("%s: data=%p, op=%d\n", __PRETTY_FUNCTION__, data, op);

	print_element_names(node, 0);

	// retrieve the dpid of this twig
	xmlNodePtr tmp = find_element(BAD_CAST "datapath-id",  node->parent->parent->children);
	assert(tmp);
	uint64_t dpid = parse_dpid(tmp->children->content);

	int rv = EXIT_SUCCESS;

	// fixme depending on the erropt (e.g. NC_EDIT_ERROPT_ROLLBACK we might still have *data set)
	assert(data);
	if (NULL == *data) {
		*data = calloc(1, sizeof(struct lsi));
		assert(*data);
	}

	if (XMLDIFF_ADD & op) {

		xmlChar buf[255];
		// check if port is already attached
		xmlStrPrintf(buf, sizeof(buf), "/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:resources/ofc:port[text()='%s']", XML_GET_CONTENT(node->children));
		xmlXPathObjectPtr xpath_obj_ptr = get_node(node->doc, namespace_mapping, buf);
		assert(xpath_obj_ptr);
		assert(xpath_obj_ptr->nodesetval);

		if (1 == xpath_obj_ptr->nodesetval->nodeNr) {

			if (NULL == LSI(data)->res.port_list_add) {
				LSI(data)->res.port_list_add = list_new();
				assert(((struct lsi* )*data)->res.port_list_add);
			}
			struct port *p = calloc(1, sizeof(struct port));
			p->resource_id = xmlNodeListGetString(node->doc, node->children, 1);
			p->op = ADD;
			p->dpid = dpid;
			list_append_data(LSI(data)->res.port_list_add, p);

			nc_verb_verbose("added to list: dpid=%lx port %s with op=%u\n", p->dpid, p->resource_id, p->op);
		} else {
			// nodeNr > 1 ==> already attached port
			nc_verb_verbose("attachment failed dpid=%lx port %s: port already attached.\n", dpid, XML_GET_CONTENT(node->children));
			rv = EXIT_FAILURE;
		}

		xmlXPathFreeObject(xpath_obj_ptr);

	} else if (XMLDIFF_REM & op) {

		if (NULL == LSI(data)->res.port_list_del) {
			LSI(data)->res.port_list_del = list_new();
			assert(((struct lsi* ) *data)->res.port_list_del);
		}
		struct port *p = calloc(1, sizeof(struct port));
		p->resource_id = xmlNodeListGetString(node->doc, node->children, 1);
		p->op = DELETE;
		p->dpid = dpid;
		list_append_data(LSI(data)->res.port_list_del, p);

		nc_verb_verbose("added to list: dpid=%lx port %s with op=%u\n", p->dpid, p->resource_id, p->op);

	} else {
		// todo implement
		nc_verb_error("not implemented");
		assert(0);
	}

	return rv;
}
예제 #24
0
/* !DO NOT ALTER FUNCTION SIGNATURE! */
int callback_ofc_capable_switch_ofc_resources_ofc_port_ofc_features (void ** data, XMLDIFF_OP op, xmlNodePtr node, struct nc_err** error)
{
	nc_verb_verbose("%s: data=%p, op=%d\n", __PRETTY_FUNCTION__, data, op);
	print_element_names(node, 0);
	return EXIT_SUCCESS;
}
예제 #25
0
int cmd_feature(const char* arg) {
	char* argv, *ptr, *state_str, *saveptr;
	int i, ret = 0;
	struct model_list* list;
	struct data_model* model;

	if (strlen(arg) < 8) {
		cmd_feature_help();
		return 1;
	}

	argv = strdupa(arg + strlen("feature "));

	ptr = strtok_r(argv, " ", &saveptr);
	if (ptr == NULL) {
		cmd_feature_help();
		return 1;
	}

	list = find_model(ptr);
	if (list == NULL) {
		nc_verb_error("No model \"%s\" found", ptr);
		return 1;
	}
	model = list->model;

	ptr = strtok_r(NULL, " ", &saveptr);

	/* we are done, no more arguments */
	if (ptr == NULL) {
		printf("Features:\n");
		if (model->features == NULL) {
			printf("\tnone\n");
			return 0;
		}
		for (i = 0; model->features[i] != NULL; ++i) {
			printf("\t%s %s\n", model->features[i]->name, (model->features[i]->enabled ? "ON" : "OFF"));
		}
		return 0;
	}

	do {
		state_str = strtok_r(NULL, " ", &saveptr);
	} while (state_str != NULL && strcmp(state_str, "on") != 0 && strcmp(state_str, "off") != 0);
	/* there was no "yes" or "no" at the end */
	if (state_str == NULL) {
		cmd_feature_help();
		return 1;
	}

	if (model->features == NULL) {
		nc_verb_error("Model does not have any features");
		return 1;
	}

	/* all features */
	if (strcmp(ptr, "*") == 0) {
		for (i = 0; model->features[i] != NULL; ++i) {
			if (strcmp(state_str, "on") == 0) {
				model->features[i]->enabled = 1;
			} else {
				model->features[i]->enabled = 0;
			}
		}
	} else {
		/* one or more features */
		ptr = argv + strlen(argv)+1;
		while (ptr != state_str) {
			for (i = 0; model->features[i] != NULL; ++i) {
				if (strcmp(model->features[i]->name, ptr) == 0) {
					if ((model->features[i]->enabled && strcmp(state_str, "on") == 0) || (!model->features[i]->enabled && strcmp(state_str, "off") == 0)) {
						nc_verb_verbose("Feature \"%s\" is already %s", ptr, state_str);
					} else if (strcmp(state_str, "on") == 0) {
						model->features[i]->enabled = 1;
					} else {
						model->features[i]->enabled = 0;
					}
					break;
				}
			}

			if (model->features[i] == NULL) {
				nc_verb_error("Model does not have the feature \"%s\"", ptr);
				ret = 1;
			}

			ptr = ptr + strlen(ptr)+1;
		}
	}

	return ret;
}
예제 #26
0
/* !DO NOT ALTER FUNCTION SIGNATURE! */
int callback_ofc_capable_switch_ofc_logical_switches_ofc_switch_ofc_controllers (void ** data, XMLDIFF_OP op, xmlNodePtr node, struct nc_err** error)
{
	nc_verb_verbose("%s: data=%p, op=%d\n", __PRETTY_FUNCTION__, data, op);
	nc_verb_verbose("currently ignored");
	return EXIT_SUCCESS;
}
int netopeer_transapi_init_ssh(void) {
	xmlDocPtr doc;
	struct nc_err* error = NULL;
	const char* str_err;

	nc_verb_verbose("Setting the default configuration for the cfgnetopeer module SSH...");

	netopeer_options.ssh_opts = calloc(1, sizeof(struct np_options_ssh));
	pthread_mutex_init(&netopeer_options.ssh_opts->client_keys_lock, NULL);

	doc = xmlReadDoc(BAD_CAST "<netopeer xmlns=\"urn:cesnet:tmc:netopeer:1.0\"><ssh><server-keys><rsa-key>/etc/ssh/ssh_host_rsa_key</rsa-key></server-keys><password-auth-enabled>true</password-auth-enabled><auth-attempts>3</auth-attempts><auth-timeout>10</auth-timeout></ssh></netopeer>",
		NULL, NULL, 0);
	if (doc == NULL) {
		nc_verb_error("Unable to parse the default cfgnetopeer SSH configuration.");
		return EXIT_FAILURE;
	}

	if (callback_n_netopeer_n_ssh_n_server_keys_n_rsa_key(NULL, XMLDIFF_ADD, NULL, doc->children->children->children->children, &error) != EXIT_SUCCESS) {
		if (error != NULL) {
			str_err = nc_err_get(error, NC_ERR_PARAM_MSG);
			if (str_err != NULL) {
				nc_verb_error(str_err);
			}
			nc_err_free(error);
		}
		xmlFreeDoc(doc);
		return EXIT_FAILURE;
	}

	if (callback_n_netopeer_n_ssh_n_password_auth_enabled(NULL, XMLDIFF_ADD, NULL, doc->children->children->children->next, &error) != EXIT_SUCCESS) {
		if (error != NULL) {
			str_err = nc_err_get(error, NC_ERR_PARAM_MSG);
			if (str_err != NULL) {
				nc_verb_error(str_err);
			}
			nc_err_free(error);
		}
		xmlFreeDoc(doc);
		return EXIT_FAILURE;
	}

	if (callback_n_netopeer_n_ssh_n_auth_attempts(NULL, XMLDIFF_ADD, NULL, doc->children->children->children->next->next, &error) != EXIT_SUCCESS) {
		if (error != NULL) {
			str_err = nc_err_get(error, NC_ERR_PARAM_MSG);
			if (str_err != NULL) {
				nc_verb_error(str_err);
			}
			nc_err_free(error);
		}
		xmlFreeDoc(doc);
		return EXIT_FAILURE;
	}

	if (callback_n_netopeer_n_ssh_n_auth_timeout(NULL, XMLDIFF_ADD, NULL, doc->children->children->children->next->next->next, &error) != EXIT_SUCCESS) {
		if (error != NULL) {
			str_err = nc_err_get(error, NC_ERR_PARAM_MSG);
			if (str_err != NULL) {
				nc_verb_error(str_err);
			}
			nc_err_free(error);
		}
		xmlFreeDoc(doc);
		return EXIT_FAILURE;
	}

	xmlFreeDoc(doc);
	return EXIT_SUCCESS;
}
예제 #28
0
파일: server.c 프로젝트: hinkey/netopeer
void listen_loop(int do_init) {
	struct client_struct* new_client;
	struct np_sock npsock = {.count = 0};
	int ret;
	struct timespec ts;
#ifdef NP_SSH
	ssh_bind sshbind = NULL;
#endif
#ifdef NP_TLS
	SSL_CTX* tlsctx = NULL;
#endif

	/* Init */
	if (do_init) {
#ifdef NP_SSH
		np_ssh_init();
#endif
#ifdef NP_TLS
		np_tls_init();
#endif
		if ((ret = pthread_create(&netopeer_state.data_tid, NULL, data_thread, NULL)) != 0) {
			nc_verb_error("%s: failed to create a thread (%s)", __func__, strerror(ret));
			return;
		}
		if ((ret = pthread_create(&netopeer_state.netconf_rpc_tid, NULL, netconf_rpc_thread, NULL)) != 0) {
			nc_verb_error("%s: failed to create a thread (%s)", __func__, strerror(ret));
			return;
		}
	}

	/* Main accept loop */
	do {
		new_client = NULL;

		/* Binds change check */
		if (netopeer_options.binds_change_flag) {
			/* BINDS LOCK */
			pthread_mutex_lock(&netopeer_options.binds_lock);

			sock_cleanup(&npsock);
			sock_listen(netopeer_options.binds, &npsock);

			netopeer_options.binds_change_flag = 0;
			/* BINDS UNLOCK */
			pthread_mutex_unlock(&netopeer_options.binds_lock);

			if (npsock.count == 0) {
				nc_verb_warning("Server is not listening on any address!");
			}
		}

#ifdef NP_SSH
		sshbind = np_ssh_server_id_check(sshbind);
#endif
#ifdef NP_TLS
		tlsctx = np_tls_server_id_check(tlsctx);
#endif

#ifndef DISABLE_CALLHOME
		/* Callhome client check */
		if (callhome_client != NULL) {
			/* CALLHOME LOCK */
			pthread_mutex_lock(&callhome_lock);
			new_client = callhome_client;
			callhome_client = NULL;
			/* CALLHOME UNLOCK */
			pthread_mutex_unlock(&callhome_lock);
		}
#endif

		/* Listen client check */
		if (new_client == NULL) {
			new_client = sock_accept(&npsock);
		}

		/* New client full structure creation */
		if (new_client != NULL) {

			/* Maximum number of sessions check */
			if (netopeer_options.max_sessions > 0) {
				ret = 0;
#ifdef NP_SSH
				ret += np_ssh_session_count();
#endif
#ifdef NP_TLS
				ret += np_tls_session_count();
#endif

				if (ret >= netopeer_options.max_sessions) {
					nc_verb_error("Maximum number of sessions reached, droppping the new client.");
					new_client->to_free = 1;
					switch (new_client->transport) {
#ifdef NP_SSH
					case NC_TRANSPORT_SSH:
						client_free_ssh((struct client_struct_ssh*)new_client);
						break;
#endif
#ifdef NP_TLS
					case NC_TRANSPORT_TLS:
						client_free_tls((struct client_struct_tls*)new_client);
						break;
#endif
					default:
						nc_verb_error("%s: internal error (%s:%d)", __func__, __FILE__, __LINE__);
					}
					free(new_client);

					/* sleep to prevent clients from immediate connection retry */
					usleep(netopeer_options.response_time*1000);
					continue;
				}
			}

			switch (new_client->transport) {
#ifdef NP_SSH
			case NC_TRANSPORT_SSH:
				ret = np_ssh_create_client((struct client_struct_ssh*)new_client, sshbind);
				if (ret != 0) {
					new_client->to_free = 1;
					client_free_ssh((struct client_struct_ssh*)new_client);
				}
				break;
#endif
#ifdef NP_TLS
			case NC_TRANSPORT_TLS:
				ret = np_tls_create_client((struct client_struct_tls*)new_client, tlsctx);
				if (ret != 0) {
					new_client->to_free = 1;
					client_free_tls((struct client_struct_tls*)new_client);
				}
				break;
#endif
			default:
				nc_verb_error("Client with an unknown transport protocol, dropping it.");
				new_client->to_free = 1;
				ret = 1;
			}

			/* client is not valid, some error occured */
			if (ret != 0) {
				free(new_client);
				continue;
			}

			/* add the client into the global clients structure */
			/* GLOBAL WRITE LOCK */
			pthread_rwlock_wrlock(&netopeer_state.global_lock);
			client_append(&netopeer_state.clients, new_client);
			/* GLOBAL WRITE UNLOCK */
			pthread_rwlock_unlock(&netopeer_state.global_lock);
		}

	} while (!quit && !restart_soft);

	/* Cleanup */
	sock_cleanup(&npsock);
#ifdef NP_SSH
	ssh_bind_free(sshbind);
#endif
#ifdef NP_TLS
	SSL_CTX_free(tlsctx);
#endif
	if (!restart_soft) {
		if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
			nc_verb_warning("%s: failed to get time (%s)", strerror(errno));
		}
		ts.tv_sec += THREAD_JOIN_QUIT_TIMEOUT;

		/* wait for all the clients to exit nicely themselves */
		if ((ret = pthread_timedjoin_np(netopeer_state.netconf_rpc_tid, NULL, &ts)) != 0) {
			nc_verb_warning("%s: failed to join the netconf RPC thread (%s)", __func__, strerror(ret));
			if (ret == ETIMEDOUT) {
				pthread_cancel(netopeer_state.netconf_rpc_tid);
			}
		}
		if ((ret = pthread_timedjoin_np(netopeer_state.data_tid, NULL, &ts)) != 0) {
			nc_verb_warning("%s: failed to join the SSH data thread (%s)", __func__, strerror(ret));
			if (ret == ETIMEDOUT) {
				pthread_cancel(netopeer_state.data_tid);
			}
		}

#ifdef NP_SSH
		np_ssh_cleanup();
#endif
#ifdef NP_TLS
		np_tls_cleanup();
#endif
	}
}

int main(int argc, char** argv) {
	struct sigaction action;
	sigset_t block_mask;

	char *aux_string = NULL, path[PATH_MAX];
	int next_option;
	int daemonize = 0, len;
	int listen_init = 1;
	struct np_module* netopeer_module = NULL, *server_module = NULL;

	/* initialize message system and set verbose and debug variables */
	if ((aux_string = getenv(ENVIRONMENT_VERBOSE)) == NULL) {
		netopeer_options.verbose = NC_VERB_ERROR;
	} else {
		netopeer_options.verbose = atoi(aux_string);
	}

	aux_string = NULL; /* for sure to avoid unwanted changes in environment */

	/* parse given options */
	while ((next_option = getopt(argc, argv, OPTSTRING)) != -1) {
		switch (next_option) {
		case 'd':
			daemonize = 1;
			break;
		case 'h':
			print_usage(argv[0]);
			break;
		case 'v':
			netopeer_options.verbose = atoi(optarg);
			break;
		case 'V':
			print_version(argv[0]);
			break;
		default:
			print_usage(argv[0]);
			break;
		}
	}

	/* set signal handler */
	sigfillset (&block_mask);
	action.sa_handler = signal_handler;
	action.sa_mask = block_mask;
	action.sa_flags = 0;
	sigaction(SIGINT, &action, NULL);
	sigaction(SIGQUIT, &action, NULL);
	sigaction(SIGABRT, &action, NULL);
	sigaction(SIGTERM, &action, NULL);
	sigaction(SIGHUP, &action, NULL);

	nc_callback_print(clb_print);

	/* normalize value if not from the enum */
	if (netopeer_options.verbose > NC_VERB_DEBUG) {
		netopeer_options.verbose = NC_VERB_DEBUG;
	}
	nc_verbosity(netopeer_options.verbose);

	/* go to the background as a daemon */
	if (daemonize == 1) {
		if (daemon(0, 0) != 0) {
			nc_verb_error("Going to background failed (%s)", strerror(errno));
			return EXIT_FAILURE;
		}
		openlog("netopeer-server", LOG_PID, LOG_DAEMON);
	} else {
		openlog("netopeer-server", LOG_PID|LOG_PERROR, LOG_DAEMON);
	}

	/* make sure we were executed by root */
	if (geteuid() != 0) {
		nc_verb_error("Failed to start, must have root privileges.");
		return EXIT_FAILURE;
	}

	/*
	 * this initialize the library and check potential ABI mismatches
	 * between the version it was compiled for and the actual shared
	 * library used.
	 */
	LIBXML_TEST_VERSION

	/* initialize library including internal datastores and maybee something more */
	if (nc_init(NC_INIT_ALL | NC_INIT_MULTILAYER) < 0) {
		nc_verb_error("Library initialization failed.");
		return EXIT_FAILURE;
	}

	server_start = 1;

restart:
	/* start NETCONF server module */
	if ((server_module = calloc(1, sizeof(struct np_module))) == NULL) {
		nc_verb_error("Creating necessary NETCONF server plugin failed!");
		return EXIT_FAILURE;
	}
	server_module->name = strdup(NCSERVER_MODULE_NAME);
	if (module_enable(server_module, 0)) {
		nc_verb_error("Starting necessary NETCONF server plugin failed!");
		free(server_module->name);
		free(server_module);
		return EXIT_FAILURE;
	}

	/* start netopeer device module - it will start all modules that are
	 * in its configuration and in server configuration */
	if ((netopeer_module = calloc(1, sizeof(struct np_module))) == NULL) {
		nc_verb_error("Creating necessary Netopeer plugin failed!");
		module_disable(server_module, 1);
		return EXIT_FAILURE;
	}
	netopeer_module->name = strdup(NETOPEER_MODULE_NAME);
	if (module_enable(netopeer_module, 0)) {
		nc_verb_error("Starting necessary Netopeer plugin failed!");
		module_disable(server_module, 1);
		free(netopeer_module->name);
		free(netopeer_module);
		return EXIT_FAILURE;
	}

	server_start = 0;
	nc_verb_verbose("Netopeer server successfully initialized.");

	listen_loop(listen_init);

	/* unload Netopeer module -> unload all modules */
	module_disable(server_module, 1);
	module_disable(netopeer_module, 1);

	/* main cleanup */

	if (!restart_soft) {
		/* close libnetconf only when shutting down or hard restarting the server */
		nc_close();
	}

	if (restart_soft) {
		nc_verb_verbose("Server is going to soft restart.");
		restart_soft = 0;
		listen_init = 0;
		goto restart;
	} else if (restart_hard) {
		nc_verb_verbose("Server is going to hard restart.");
		len = readlink("/proc/self/exe", path, PATH_MAX);
		path[len] = 0;
		xmlCleanupParser();
		execv(path, argv);
	}

	/*
	 *Free the global variables that may
	 *have been allocated by the parser.
	 */
	xmlCleanupParser();

	return EXIT_SUCCESS;
}
예제 #29
0
int main (int argc, char** argv)
{
	conn_t* conn = NULL;

	struct sigaction action;
	sigset_t block_mask;

	char *aux_string = NULL, path[PATH_MAX];
	int next_option, ret;
	int daemonize = 0, len;
	int verbose = 0;
	struct module * netopeer_module = NULL, *server_module = NULL;

	/* initialize message system and set verbose and debug variables */
	if ((aux_string = getenv (ENVIRONMENT_VERBOSE)) == NULL) {
		verbose = NC_VERB_ERROR;
	} else {
		verbose = atoi (aux_string);
	}

	aux_string = NULL; /* for sure to avoid unwanted changes in environment */

	/* parse given options */
	while ((next_option = getopt (argc, argv, OPTSTRING)) != -1) {
		switch (next_option) {
		case 'd':
			daemonize = 1;
			break;
		case 'h':
			print_usage (argv[0]);
			break;
		case 'v':
			verbose = atoi (optarg);
			break;
		case 'V':
			print_version (argv[0]);
			break;
		default:
			print_usage (argv[0]);
			break;
		}
	}

	/* set signal handler */
	sigfillset (&block_mask);
	action.sa_handler = signal_handler;
	action.sa_mask = block_mask;
	action.sa_flags = 0;
	sigaction (SIGINT, &action, NULL);
	sigaction (SIGQUIT, &action, NULL);
	sigaction (SIGABRT, &action, NULL);
	sigaction (SIGTERM, &action, NULL);
	sigaction (SIGKILL, &action, NULL);
	sigaction (SIGHUP, &action, NULL);

	nc_callback_print (clb_print);

	/* normalize value if not from the enum */
	if (verbose < NC_VERB_ERROR) {
		nc_verbosity (NC_VERB_ERROR);
	} else if (verbose > NC_VERB_DEBUG) {
		nc_verbosity (NC_VERB_DEBUG);
	} else {
		nc_verbosity (verbose);
	}

	/* go to the background as a daemon */
	if (daemonize == 1) {
		if (daemon(0, 0) != 0) {
			nc_verb_error("Going to background failed (%s)", strerror(errno));
			return (EXIT_FAILURE);
		}
		openlog("netopeer-server", LOG_PID, LOG_DAEMON);
	} else {
		openlog("netopeer-server", LOG_PID|LOG_PERROR, LOG_DAEMON);
	}

	/* make sure we were executed by root */
	if (geteuid() != 0) {
		nc_verb_error("Failed to start, must have root privileges.");
		return (EXIT_FAILURE);
	}

	/*
	 * this initialize the library and check potential ABI mismatches
	 * between the version it was compiled for and the actual shared
	 * library used.
	 */
	LIBXML_TEST_VERSION

	/* initialize library including internal datastores and maybee something more */
	if ((ret = nc_init (NC_INIT_ALL | NC_INIT_MULTILAYER)) < 0) {
		nc_verb_error("Library initialization failed.");
		return (EXIT_FAILURE);
	}

	/* Initiate communication subsystem for communicate with agents */
	conn = comm_init(ret & NC_INITRET_RECOVERY);
	if (conn == NULL) {
		nc_verb_error("Communication subsystem not initiated.");
		return (EXIT_FAILURE);
	}

	server_start = 1;

restart:
	/* start NETCONF server module */
	if ((server_module = calloc(1, sizeof(struct module))) == NULL) {
		nc_verb_error("Creating necessary NETCONF server plugin failed!");
		comm_destroy(conn);
		return(EXIT_FAILURE);
	}
	server_module->name = strdup(NCSERVER_MODULE_NAME);
	if (module_enable(server_module, 0)) {
		nc_verb_error("Starting necessary NETCONF server plugin failed!");
		free(server_module->name);
		free(server_module);
		comm_destroy(conn);
		return EXIT_FAILURE;
	}

	/* start netopeer device module - it will start all modules that are
	 * in its configuration and in server configuration */
	if ((netopeer_module = calloc(1, sizeof(struct module))) == NULL) {
		nc_verb_error("Creating necessary Netopeer plugin failed!");
		module_disable(server_module, 1);
		comm_destroy(conn);
		return(EXIT_FAILURE);
	}
	netopeer_module->name = strdup(NETOPEER_MODULE_NAME);
	if (module_enable(netopeer_module, 0)) {
		nc_verb_error("Starting necessary Netopeer plugin failed!");
		module_disable(server_module, 1);
		free(netopeer_module->name);
		free(netopeer_module);
		comm_destroy(conn);
		return EXIT_FAILURE;
	}

	server_start = 0;
	nc_verb_verbose("Netopeer server successfully initialized.");

	while (!done) {
		comm_loop(conn, 500);
	}

	/* unload Netopeer module -> unload all modules */
	module_disable(server_module, 1);
	module_disable(netopeer_module, 1);

	/* main cleanup */

	if (!restart_soft) {
		/* close connection and destroy all sessions only when shutting down or hard restarting the server */
		comm_destroy(conn);
		server_sessions_destroy_all ();
		nc_close ();
	}

	/*
	 *Free the global variables that may
	 *have been allocated by the parser.
	 */
	xmlCleanupParser ();

	if (restart_soft) {
		nc_verb_verbose("Server is going to soft restart.");
		restart_soft = 0;
		done = 0;
		goto restart;
	} else if (restart_hard) {
		nc_verb_verbose("Server is going to hard restart.");
		len = readlink("/proc/self/exe", path, PATH_MAX);
		path[len] = 0;
		execv(path, argv);
	}

	return (EXIT_SUCCESS);
}
예제 #30
0
/* !DO NOT ALTER FUNCTION SIGNATURE! */
int callback_ofc_capable_switch_ofc_logical_switches_ofc_switch (void ** data, XMLDIFF_OP op, xmlNodePtr node, struct nc_err** error)
{
	nc_verb_verbose("%s: data=%p, op=%d\n", __PRETTY_FUNCTION__, data, op);
	print_element_names(node, 0);

	if (NULL == ofc_state.lsi_list) {
		ofc_state.lsi_list = list_new();
		assert(ofc_state.lsi_list);
	}

	assert(data);
	assert(*data);

	if (!(XMLDIFF_REM & op)) {
		list_append_data(ofc_state.lsi_list, *data);
	}

	int rv = EXIT_SUCCESS;
	if (XMLDIFF_ADD & op) {
		assert(XMLDIFF_CHAIN & op);

		nc_verb_verbose("create new lsi (dpid=%lu, name=%s)\n", LSI(data)->dpid, LSI(data)->dpname);
		if (lsi_create(ofc_state.xmp_client_handle, *data)) {
			rv = EXIT_FAILURE;
		}

	} else if (XMLDIFF_REM& op) {
		assert(XMLDIFF_CHAIN & op);

		nc_verb_verbose("destroy lsi (dpid=%lu, name=%s)\n", LSI(data)->dpid, LSI(data)->dpname);
		if ( lsi_destroy(ofc_state.xmp_client_handle, LSI(data)->dpid) ) {
			rv = EXIT_FAILURE;
		}

		// cannot have a port add during a lsi destroy
		assert(NULL == LSI(data)->res.port_list_add);

		// check if there were ports attached, then clean the list, because detachment takes place during lsi destruction
		if (NULL != LSI(data)->res.port_list_del) {
			struct port *p;
			while ((p = list_pop_head(LSI(data)->res.port_list_del))) {
				xmlFree(p->resource_id);
				free(p);
			}
		}

		// no need to deal with controllers seperately here

		lsi_cleanup(*data);


	} else if (XMLDIFF_MOD & op) {
		// direct sub elements changed
		nc_verb_error("not implemented XMLDIFF_MOD");
		assert(0);
	} else if (XMLDIFF_CHAIN & op) {
		// resources or controllers changed (attachment of ports handled in parent)

		nc_verb_verbose("XMLDIFF_CHAIN\n");

		// check dpid
		if (0 == LSI(data)->dpid) {
			xmlNodePtr tmp = find_element(BAD_CAST "datapath-id",  node->children);
			assert(tmp);
			uint64_t dpid = parse_dpid(tmp->children->content);

			if (LSI(data)->dpid != dpid) {
				LSI(data)->dpid = dpid;
			}
		}

		if (LSI(data)->controller_list_add) {
			lsi_connect_to_controller(ofc_state.xmp_client_handle, LSI(data));
		}

		if (LSI(data)->controller_list_del) {
			// fixme implement
			// assert(0);
		}

	} else {
		nc_verb_error("unsupported op");
		assert(0);
	}

	*data = NULL;

	return rv;
}