static struct json_object * respondd_provider_neighbours(void) {
    lldpctl_conn_t *conn;
    lldpctl_atom_t *ifaces, *iface, *port, *neighbors, *neighbor;
    const char *ctlname, *neighmac, *portmac;
    struct json_object *ret, *ret_lldp, *neighbors_obj;

    ret_lldp = json_object_new_object();

    ctlname = lldpctl_get_default_transport();
    conn    = lldpctl_new_name(ctlname, NULL, NULL, NULL);
    ifaces  = lldpctl_get_interfaces(conn);
    lldpctl_atom_foreach(ifaces, iface) {
        port = lldpctl_get_port(iface);
        // check if Port ID Subtype is MAC address
        if (lldpctl_atom_get_int(port, lldpctl_k_port_id_subtype) != LLDP_PORTID_SUBTYPE_LLADDR)
            continue;

        portmac = lldpctl_atom_get_str(port, lldpctl_k_port_id);
        if (!portmac)
            continue;

        neighbors_obj = json_object_new_object();
        neighbors = lldpctl_atom_get(port, lldpctl_k_port_neighbors);
        lldpctl_atom_foreach(neighbors, neighbor) {
            // check if Chassis ID Subtype is MAC address
            if (lldpctl_atom_get_int(neighbor, lldpctl_k_chassis_id_subtype) != LLDP_CHASSISID_SUBTYPE_LLADDR)
                continue;

            neighmac = lldpctl_atom_get_str(neighbor, lldpctl_k_chassis_id);
            if (!neighmac)
                continue;

            json_object_object_add(neighbors_obj, neighmac, json_object_new_object());
        }
        json_object_object_add(ret_lldp, portmac, neighbors_obj);
    }
Beispiel #2
0
int
main(int argc, char *argv[])
{
	int ch, debug = 1, rc = EXIT_FAILURE;
	const char *fmt = "plain";
	lldpctl_conn_t *conn = NULL;
	const char *options = is_lldpctl(argv[0])?"hdvf:":"hdsvf:c:u:";

	int gotinputs = 0;
	struct inputs inputs;
	TAILQ_INIT(&inputs);

	ctlname = lldpctl_get_default_transport();

	signal(SIGHUP, SIG_IGN);

	/* Initialize logging */
	while ((ch = getopt(argc, argv, options)) != -1) {
		switch (ch) {
		case 'd': debug++; break;
		case 's': debug--; break;
		}
	}
	log_init(debug, __progname);

	/* Get and parse command line options */
	optind = 1;
	while ((ch = getopt(argc, argv, options)) != -1) {
		switch (ch) {
		case 'd': break;
		case 's': break;
		case 'h':
			usage();
			break;
		case 'u':
			ctlname = optarg;
			break;
		case 'v':
			fprintf(stdout, "%s\n", PACKAGE_VERSION);
			exit(0);
			break;
		case 'f':
			fmt = optarg;
			break;
		case 'c':
			gotinputs = 1;
			input_append(optarg, &inputs, 1);
			break;
		default:
			usage();
		}
	}

	/* Disable SIGPIPE */
	signal(SIGPIPE, SIG_IGN);

	/* Register commands */
	root = register_commands();

	/* Make a connection */
	log_debug("lldpctl", "connect to lldpd");
	conn = lldpctl_new_name(ctlname, NULL, NULL, NULL);
	if (conn == NULL) goto end;

	/* Process file inputs */
	while (gotinputs && !TAILQ_EMPTY(&inputs)) {
		/* coverity[use_after_free]
		   TAILQ_REMOVE does the right thing */
		struct input *first = TAILQ_FIRST(&inputs);
		log_debug("lldpctl", "process: %s", first->name);
		FILE *file = fopen(first->name, "r");
		if (file) {
			size_t len;
			char *line;
			while ((line = fgetln(file, &len))) {
				line = strndup(line, len);
				if (line[len - 1] == '\n') {
					line[len - 1] = '\0';
					parse_and_exec(conn, fmt, line);
				}
				free(line);
			}
			fclose(file);
		} else {
			log_warn("lldpctl", "unable to open %s",
			    first->name);
		}
		TAILQ_REMOVE(&inputs, first, next);
		free(first->name);
		free(first);
	}

	/* Process additional arguments. First if we are lldpctl (interfaces) */
	if (is_lldpctl(NULL)) {
		char *line = NULL;
		for (int i = optind; i < argc; i++) {
			char *prev = line;
			if (asprintf(&line, "%s%s%s",
				prev?prev:"show neigh ports ", argv[i],
				(i == argc - 1)?" details":",") == -1) {
				log_warnx("lldpctl", "not enough memory to build list of interfaces");
				free(prev);
				goto end;
			}
			free(prev);
		}
		if (line == NULL && (line = strdup("show neigh details")) == NULL) {
			log_warnx("lldpctl", "not enough memory to build command line");
			goto end;
		}
		log_debug("lldpctl", "execute %s", line);
		if (parse_and_exec(conn, fmt, line) != -1)
			rc = EXIT_SUCCESS;
		free(line);
		goto end;
	}

	/* Then, if we are regular lldpcli (command line) */
	if (optind < argc) {
		const char **cargv;
		int cargc;
		cargv = &((const char **)argv)[optind];
		cargc = argc - optind;
		if (cmd_exec(conn, fmt, cargc, cargv) != -1)
			rc = EXIT_SUCCESS;
		goto end;
	}

	if (gotinputs) {
		rc = EXIT_SUCCESS;
		goto end;
	}

	/* Interactive session */
#ifdef HAVE_LIBREADLINE
	rl_bind_key('?',  cmd_help);
	rl_bind_key('\t', cmd_complete);
#endif
	const char *line;
	do {
		if ((line = readline(prompt()))) {
			int n = parse_and_exec(conn, fmt, line);
			(void)n;
#ifdef HAVE_READLINE_HISTORY
			if (n != 0) add_history(line);
#endif
		}
	} while (!must_exit && line != NULL);
	rc = EXIT_SUCCESS;

end:
	while (!TAILQ_EMPTY(&inputs)) {
		/* coverity[use_after_free]
		   TAILQ_REMOVE does the right thing */
		struct input *first = TAILQ_FIRST(&inputs);
		TAILQ_REMOVE(&inputs, first, next);
		free(first->name);
		free(first);
	}
	if (conn) lldpctl_release(conn);
	if (root) commands_free(root);
	return rc;
}