Add lttng URI support and default network ports
authorDavid Goulet <dgoulet@efficios.com>
Wed, 13 Jun 2012 21:08:05 +0000 (17:08 -0400)
committerDavid Goulet <dgoulet@efficios.com>
Wed, 13 Jun 2012 21:08:05 +0000 (17:08 -0400)
This commit simply adds the lttng_uri API/ABI to the upstream branch.
Three functions are provided by common/uri.h and are usable by linking
with libcommon.

The default network ports are also added for network streaming for both
control and data stream.

Signed-off-by: David Goulet <dgoulet@efficios.com>
include/lttng/lttng.h
src/common/Makefile.am
src/common/defaults.h
src/common/uri.c [new file with mode: 0644]
src/common/uri.h [new file with mode: 0644]

index c80e2827e585ba626772c0f7506805d819115c99..73f291466be9368e183d2a856603919b1b67cda1 100644 (file)
@@ -23,6 +23,7 @@
 #define _LTTNG_H
 
 #include <limits.h>
+#include <netinet/in.h>
 #include <stdint.h>
 #include <sys/types.h>
 
  */
 #define LTTNG_SYMBOL_NAME_LEN             256
 
+/*
+ * Maximum length of a domain name. This is the limit for the total length of a
+ * domain name specified by the RFC 1035 (https://www.ietf.org/rfc/rfc1035.txt)
+ */
+#define LTTNG_MAX_DNNAME                  255
+
 /*
  * Every lttng_event_* structure both apply to kernel event and user-space
  * event.
@@ -124,6 +131,62 @@ enum lttng_calibrate_type {
        LTTNG_CALIBRATE_FUNCTION              = 0,
 };
 
+/* Destination type of lttng URI */
+enum lttng_dst_type {
+       LTTNG_DST_IPV4,         /* IPv4 protocol */
+       LTTNG_DST_IPV6,         /* IPv6 protocol */
+       LTTNG_DST_PATH,         /* Local file system */
+};
+
+/* Type of lttng URI where it is a final destination or a hop */
+enum lttng_uri_type {
+       LTTNG_URI_DST,  /* The URI is a final destination */
+       /*
+        * Hop are not supported yet but planned for a future release.
+        *
+       LTTNG_URI_HOP,
+       */
+};
+
+/* Communication stream type of a lttng URI */
+enum lttng_stream_type {
+       LTTNG_STREAM_CONTROL,
+       LTTNG_STREAM_DATA,
+};
+
+/*
+ * Protocol type of a lttng URI. The value 0 indicate that the proto_type field
+ * should be ignored.
+ */
+enum lttng_proto_type {
+       LTTNG_TCP                             = 1,
+       /*
+        * UDP protocol is not supported for now.
+        *
+       LTTNG_UDP                             = 2,
+       */
+};
+
+/*
+ * Structure representing an URI supported by lttng.
+ */
+#define LTTNG_URI_PADDING1_LEN         16
+#define LTTNG_URI_PADDING2_LEN         LTTNG_SYMBOL_NAME_LEN + 32
+struct lttng_uri {
+       enum lttng_dst_type dtype;
+       enum lttng_uri_type utype;
+       enum lttng_stream_type stype;
+       enum lttng_proto_type proto;
+       in_port_t port;
+       char padding[LTTNG_URI_PADDING1_LEN];
+       union {
+               char ipv4[INET_ADDRSTRLEN];
+               char ipv6[INET6_ADDRSTRLEN];
+               char path[PATH_MAX];
+               char padding[LTTNG_URI_PADDING2_LEN];
+       } dst;
+};
+
 /*
  * The structures should be initialized to zero before use.
  */
index 460f2a2de989bc65605f25ba67eb7102245191d4..1cf70720479f782548adae83e232edbfd4661940 100644 (file)
@@ -4,11 +4,11 @@ SUBDIRS = compat hashtable kernel-ctl sessiond-comm kernel-consumer ust-consumer
 
 AM_CFLAGS = -fno-strict-aliasing
 
-noinst_HEADERS = lttng-kernel.h defaults.h macros.h error.h futex.h
+noinst_HEADERS = lttng-kernel.h defaults.h macros.h error.h futex.h uri.h
 
 noinst_LTLIBRARIES = libcommon.la
 
-libcommon_la_SOURCES = runas.c runas.h common.h futex.c futex.h
+libcommon_la_SOURCES = runas.c runas.h common.h futex.c futex.h uri.c uri.h
 
 # Consumer library
 noinst_LTLIBRARIES += libconsumer.la
index 5ee6562d91906b01b54b7909b7148a704f9dc9ce..53caf62acab033b31d775540199d61c1831af4b9 100644 (file)
  */
 #define DEFAULT_SEM_WAIT_TIMEOUT            30    /* in seconds */
 
+/* Default network ports for trace streaming support */
+#define DEFAULT_NETWORK_CONTROL_PORT        5342
+#define DEFAULT_NETWORK_DATA_PORT           5343
+
 #endif /* _DEFAULTS_H */
diff --git a/src/common/uri.c b/src/common/uri.c
new file mode 100644 (file)
index 0000000..3a58aed
--- /dev/null
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2012 - David Goulet <dgoulet@efficios.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License, version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#define _GNU_SOURCE
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+
+#include <common/common.h>
+#include <common/defaults.h>
+
+#include "uri.h"
+
+enum uri_proto_code {
+       P_NET, P_NET6, P_FILE, P_TCP, P_TCP6,
+};
+
+struct uri_proto {
+       char *name;
+       enum uri_proto_code code;
+       enum lttng_proto_type type;
+       enum lttng_dst_type dtype;
+};
+
+/* Supported protocols */
+static const struct uri_proto proto_uri[] = {
+       { .name = "file", .code = P_FILE, .type = 0, .dtype = LTTNG_DST_PATH},
+       { .name = "net", .code = P_NET, .type = LTTNG_TCP, .dtype = LTTNG_DST_IPV4 },
+       { .name = "net6", .code = P_NET6, .type = LTTNG_TCP, .dtype = LTTNG_DST_IPV6 },
+       { .name = "tcp", .code = P_TCP, .type = LTTNG_TCP, .dtype = LTTNG_DST_IPV4 },
+       { .name = "tcp6", .code = P_TCP6, .type = LTTNG_TCP, .dtype = LTTNG_DST_IPV6 },
+       { .name = NULL }
+};
+
+/*
+ * Validate if proto is a supported protocol from proto_uri array.
+ */
+static const struct uri_proto *validate_protocol(char *proto)
+{
+       const struct uri_proto *supported;
+
+       /* Safety net */
+       if (proto == NULL) {
+               goto end;
+       }
+
+       for (supported = &proto_uri[0];
+                       supported->name != NULL; ++supported) {
+               if (strncmp(proto, supported->name, strlen(proto)) == 0) {
+                       goto end;
+               }
+       }
+
+       /* Proto not found */
+       return NULL;
+
+end:
+       return supported;
+}
+
+/*
+ * Compare two URIs.
+ *
+ * Return 0 if equal else 1.
+ */
+int uri_compare(struct lttng_uri *uri1, struct lttng_uri *uri2)
+{
+       return memcmp(uri1, uri2, sizeof(struct lttng_uri));
+}
+
+/*
+ * Free URI memory.
+ */
+void uri_free(struct lttng_uri *uri)
+{
+       /* Safety check */
+       if (uri != NULL) {
+               free(uri);
+       }
+}
+
+/*
+ * Return an allocated URI.
+ */
+struct lttng_uri *uri_create(void)
+{
+       struct lttng_uri *uri;
+
+       uri = zmalloc(sizeof(struct lttng_uri));
+       if (uri == NULL) {
+               PERROR("zmalloc uri");
+       }
+
+       return uri;
+}
+
+static int set_ip_address(const char *addr, int af, char *dst, size_t size)
+{
+       int ret;
+       unsigned char buf[sizeof(struct in6_addr)];
+       struct hostent *record;
+
+       /* Network protocol */
+       ret = inet_pton(af, addr, buf);
+       if (ret < 1) {
+               /* We consider the dst to be an hostname or an invalid IP char */
+               record = gethostbyname2(addr, af);
+               if (record == NULL) {
+                       /* At this point, the IP or the hostname is bad */
+                       printf("bad hostname\n");
+                       goto error;
+               }
+
+               /* Translate IP to string */
+               (void) inet_ntop(af, record->h_addr_list[0], dst, size);
+       } else {
+               memcpy(dst, addr, size);
+       }
+
+       return 0;
+
+error:
+       return -1;
+}
+
+ssize_t uri_parse(const char *str_uri, struct lttng_uri **uris)
+{
+       int ret;
+       /* Size of the uris array. Default is 1 */
+       ssize_t size = 1;
+       char net[6], dst[LTTNG_MAX_DNNAME + 1];
+       unsigned int ctrl_port = DEFAULT_NETWORK_CONTROL_PORT;
+       unsigned int data_port = DEFAULT_NETWORK_DATA_PORT;
+       struct lttng_uri *uri;
+       const struct uri_proto *proto;
+
+       /*
+        * The first part is the protocol portion of a maximum of 5 bytes for now.
+        * (tcp, tcp6, udp, udp6, file, net). The second part is the hostname or IP
+        * address. The 255 bytes size is the limit found in the RFC 1035 for the
+        * total length of a domain name (https://www.ietf.org/rfc/rfc1035.txt).
+        * Finally, with the net:// protocol, two ports can be specified.
+        */
+
+       ret = sscanf(str_uri, "%5[^:]://", net);
+       if (ret < 1) {
+               printf("bad protocol\n");
+               goto error;
+       }
+
+       DBG3("URI protocol : %s", str_uri);
+
+       proto = validate_protocol(net);
+       if (proto == NULL) {
+               printf("no protocol\n");
+               ret = -1;
+               goto error;
+       }
+
+       if (proto->code == P_NET || proto->code == P_NET6) {
+               /* Special case for net:// which requires two URI object */
+               size = 2;
+       }
+
+       /* Parse the rest of the URI */
+       ret = sscanf(str_uri + strlen(net), "://%255[^:]:%u:%u", dst,
+                       &ctrl_port, &data_port);
+       if (ret < 0) {
+               printf("bad URI\n");
+               goto error;
+       }
+
+       /* We have enough valid information to create URI(s) object */
+
+       /* Allocate URI array */
+       uri = zmalloc(sizeof(struct lttng_uri) * size);
+       if (uri == NULL) {
+               PERROR("zmalloc uri");
+               goto error;
+       }
+
+       /* Copy generic information */
+       uri[0].dtype = proto->dtype;
+       uri[0].proto = proto->type;
+       uri[0].port = ctrl_port;
+
+       DBG3("URI dtype: %d, proto: %d, port: %d", proto->dtype, proto->type,
+                       ctrl_port);
+
+       switch (proto->code) {
+       case P_FILE:
+               memcpy(uri[0].dst.path, dst, sizeof(uri[0].dst.path));
+               /* Reset port for the file:// URI */
+               uri[0].port = 0;
+               DBG3("URI file destination: %s", dst);
+               break;
+       case P_NET:
+               ret = set_ip_address(dst, AF_INET, uri[0].dst.ipv4,
+                               sizeof(uri[0].dst.ipv4));
+               if (ret < 0) {
+                       goto free_error;
+               }
+
+               memcpy(uri[1].dst.ipv4, uri[0].dst.ipv4, sizeof(uri[1].dst.ipv4));
+
+               uri[1].dtype = proto->dtype;
+               uri[1].proto = proto->type;
+               uri[1].port = data_port;
+               break;
+       case P_NET6:
+               ret = set_ip_address(dst, AF_INET6, uri[0].dst.ipv6,
+                               sizeof(uri[0].dst.ipv6));
+               if (ret < 0) {
+                       goto free_error;
+               }
+
+               memcpy(uri[1].dst.ipv6, uri[0].dst.ipv6, sizeof(uri[1].dst.ipv6));
+
+               uri[1].dtype = proto->dtype;
+               uri[1].proto = proto->type;
+               uri[1].port = data_port;
+               break;
+       case P_TCP:
+               ret = set_ip_address(dst, AF_INET, uri[0].dst.ipv4,
+                               sizeof(uri[0].dst.ipv4));
+               if (ret < 0) {
+                       goto free_error;
+               }
+               break;
+       case P_TCP6:
+               ret = set_ip_address(dst, AF_INET6, uri[0].dst.ipv6,
+                               sizeof(uri[0].dst.ipv6));
+               if (ret < 0) {
+                       goto free_error;
+               }
+               break;
+       default:
+               goto free_error;
+       }
+
+       *uris = uri;
+
+       return size;
+
+free_error:
+       free(uri);
+error:
+       return -1;
+}
diff --git a/src/common/uri.h b/src/common/uri.h
new file mode 100644 (file)
index 0000000..959b9a6
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2012 - David Goulet <dgoulet@efficios.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License, version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _LTT_URI_H
+#define _LTT_URI_H
+
+#include <lttng/lttng.h>
+
+int uri_compare(struct lttng_uri *uri1, struct lttng_uri *uri2);
+void uri_free(struct lttng_uri *uri);
+ssize_t uri_parse(const char *str_uri, struct lttng_uri **uris);
+
+#endif /* _LTT_URI_H */
This page took 0.030932 seconds and 4 git commands to generate.