lldp_CHECK_SNMP
fi
+AC_ARG_WITH([xml],
+ AC_HELP_STRING(
+ [--with-xml],
+ [Enable XML output via libxml2 @<:@default=no:>@]
+ ))
+if test x"$with_xml" = x"yes"; then
+ lldp_CHECK_XML2
+fi
+
# Privsep settings
lldp_ARG_WITH([privsep-user], [Which user to use for privilege separation], [_lldpd])
lldp_ARG_WITH([privsep-group], [Which group to use for privilege separation], [_lldpd])
# Output results
AM_CONDITIONAL([HAVE_CHECK], [test x"$have_check" = x"yes"])
AM_CONDITIONAL([USE_SNMP], [test x"$with_snmp" = x"yes"])
+AM_CONDITIONAL([USE_XML], [test x"$with_xml" = x"yes"])
AC_OUTPUT
cat <<EOF
DOT1...........: $enable_dot1
DOT3...........: $enable_dot3
Listen on VLAN.: $enable_listenvlan
+ XML output.....: ${with_xml-no}
---------------------------------------------
Check the above options and compile with:
--- /dev/null
+#
+# lldp_CHECK_XML2
+#
+
+
+AC_DEFUN([lldp_CHECK_XML2], [
+ AC_PATH_TOOL([XML2_CONFIG], [xml2-config], [no])
+ if test x"$XML2_CONFIG" = x"no"; then
+ AC_MSG_ERROR([*** unable to find xml2-config])
+ fi
+ XML2_LIBS=`${XML2_CONFIG} --libs`
+ XML2_CFLAGS=`${XML2_CONFIG} --cflags`
+
+ _save_flags="$CFLAGS"
+ CFLAGS="$CFLAGS ${XML2_CFLAGS}"
+ AC_MSG_CHECKING([whether C compiler supports flag "${XML2_CFLAGS}" from libxml2])
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([
+int main(void);
+],
+[
+{
+ return 0;
+}
+])],[AC_MSG_RESULT(yes)],[
+AC_MSG_RESULT(no)
+AC_MSG_ERROR([*** incorrect CFLAGS from xml2-config])])
+ AC_CHECK_LIB([xml2], [xmlNewTextWriterDoc], [],
+ [AC_MSG_ERROR([*** unable to use xml2])], ${XML2_LIBS})
+ AC_SUBST([XML2_LIBS])
+ AC_SUBST([XML2_CFLAGS])
+ AC_DEFINE_UNQUOTED([USE_XML], 1, [Define to indicate to enable XML support])
+
+ CFLAGS="$_save_flags"
+])
.Bl -tag -width Ds
.It Fl d
Enable more debugging information.
+.It Fl f Ar format
+Choose the output format. Currently
+.Em plain
+and
+.Em xml
+formats are available. The default is
+.Em plain.
.It Fl L Ar location
Enable the transmission of LLDP-MED location TLV for the given
interfaces. This option can be repeated several times to enable the
liblldpd_la_CFLAGS = @NETSNMP_CFLAGS@
lldpd_LDADD += @NETSNMP_LIBS@
endif
+
+if USE_XML
+lldpctl_SOURCES += xml_writer.c
+lldpctl_CFLAGS = @XML2_CFLAGS@
+lldpctl_LDADD += @XML2_LIBS@
+endif
+
+
free(value);
break;
default:
- LLOG_WARN("unknown location data format: \n %s",
- dump(port->p_med_location[i].data,
- port->p_med_location[i].data_len, 20, ' '));
+ tag_attr(w, "type", "", "unknown");
+ tag_data(w, dump(port->p_med_location[i].data,
+ port->p_med_location[i].data_len, 20, ' '));
}
tag_end(w);
}
}
void
-display_interfaces(int s, int argc, char *argv[])
+display_interfaces(int s, const char * fmt, int argc, char *argv[])
{
struct writer * w;
int i, nb;
struct lldpd_port port;
char sep[80];
- w = txt_init( stdout );
+ if ( strcmp(fmt,"plain") == 0 ) {
+ w = txt_init( stdout );
+ }
+#ifdef USE_XML
+ else if ( strcmp(fmt,"xml") == 0 ) {
+ w = xml_init( stdout );
+ }
+#endif
+ else {
+ w = txt_init( stdout );
+ }
memset(sep, '-', 79);
sep[79] = 0;
get_interfaces(int s, struct interfaces *ifs);
extern void
-display_interfaces(int s, int argc, char *argv[]);
+display_interfaces(int s, const char * fmt, int argc, char *argv[]);
static void
usage(void)
main(int argc, char *argv[])
{
int ch, s, debug = 1;
+ char * fmt = "plain";
#define ACTION_SET_LOCATION 1
int action = 0;
/*
* Get and parse command line options
*/
- while ((ch = getopt(argc, argv, "dL:")) != -1) {
+ while ((ch = getopt(argc, argv, "df:L:")) != -1) {
switch (ch) {
case 'd':
debug++;
break;
+ case 'f':
+ fmt = optarg;
+ break;
case 'L':
#ifdef ENABLE_LLDPMED
action = ACTION_SET_LOCATION;
break;
#endif
default:
- display_interfaces(s, argc, argv);
+ display_interfaces(s, fmt, argc, argv);
}
close(s);
extern struct writer * txt_init( FILE * );
+#ifdef USE_XML
+extern struct writer * xml_init( FILE * );
+#endif
+
#endif /* _WRITER_H */
--- /dev/null
+/*
+ * Copyright (c) 2010 Andreas Hofmeister <andi@collax.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libxml/encoding.h>
+#include <libxml/xmlwriter.h>
+
+#include "writer.h"
+#include "lldpd.h"
+
+struct xml_writer_private {
+ xmlTextWriterPtr xw;
+ xmlDocPtr doc;
+};
+
+void xml_start(struct writer * w , const char * tag, const char * descr ) {
+ struct xml_writer_private * p = w->priv;
+
+ if (xmlTextWriterStartElement(p->xw, BAD_CAST tag) < 0)
+ LLOG_WARN("cannot start '%s' element\n", tag);
+}
+
+void xml_attr(struct writer * w, const char * tag, const char * descr, const char * value ) {
+ struct xml_writer_private * p = w->priv;
+
+ if (xmlTextWriterWriteFormatAttribute(p->xw, BAD_CAST tag, "%s", value) < 0)
+ LLOG_WARN("cannot add attribute %s with value %s\n", tag, value);
+}
+
+void xml_data(struct writer * w, const char * data) {
+ struct xml_writer_private * p = w->priv;
+
+ if (xmlTextWriterWriteString(p->xw, BAD_CAST data) < 0 )
+ LLOG_WARN("cannot add '%s' as data to element\n", data);
+}
+
+void xml_end(struct writer * w) {
+ struct xml_writer_private * p = w->priv;
+
+ if (xmlTextWriterEndElement(p->xw) < 0 )
+ LLOG_WARN("cannot end element\n");
+}
+
+#define MY_ENCODING "UTF-8"
+
+void xml_finish(struct writer * w) {
+ struct xml_writer_private * p = w->priv;
+ int failed = 0;
+
+ if (xmlTextWriterEndDocument(p->xw) < 0 ) {
+ LLOG_WARN("cannot finish document\n");
+ failed = 1;
+ }
+
+ xmlFreeTextWriter(p->xw);
+
+ if ( ! failed )
+ xmlSaveFileEnc("-", p->doc, MY_ENCODING);
+
+ xmlFreeDoc(p->doc);
+
+ free( w->priv );
+ free( w );
+}
+
+struct writer * xml_init(FILE * fh) {
+
+ struct writer * result;
+ struct xml_writer_private * priv;
+
+ priv = malloc( sizeof( *priv ) );
+ if ( ! priv ) {
+ fatalx("out of memory\n");
+ return NULL;
+ }
+
+ priv->xw = xmlNewTextWriterDoc(&(priv->doc), 0);
+ if ( ! priv->xw ) {
+ fatalx("cannot create xml writer\n");
+ return NULL;
+ }
+
+ xmlTextWriterSetIndent(priv->xw, 4);
+
+ if (xmlTextWriterStartDocument(priv->xw, NULL, MY_ENCODING, NULL) < 0 ) {
+ fatalx("cannot start xml document\n");
+ return NULL;
+ }
+
+ result = malloc( sizeof( struct writer ) );
+ if ( ! result ) {
+ fatalx("out of memory\n");
+ return NULL;
+ }
+
+ result->priv = priv;
+ result->start = xml_start;
+ result->attr = xml_attr;
+ result->data = xml_data;
+ result->end = xml_end;
+ result->finish= xml_finish;
+
+ return result;
+}
+