2 * Copyright (C) 2012 - David Goulet <dgoulet@efficios.com>
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License, version 2 only, as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc., 51
15 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 #include <arpa/inet.h>
23 #include <sys/socket.h>
25 #include <common/common.h>
26 #include <common/defaults.h>
31 P_NET
, P_NET6
, P_FILE
, P_TCP
, P_TCP6
,
36 enum uri_proto_code code
;
37 enum lttng_proto_type type
;
38 enum lttng_dst_type dtype
;
41 /* Supported protocols */
42 static const struct uri_proto proto_uri
[] = {
43 { .name
= "file", .code
= P_FILE
, .type
= 0, .dtype
= LTTNG_DST_PATH
},
44 { .name
= "net", .code
= P_NET
, .type
= LTTNG_TCP
, .dtype
= LTTNG_DST_IPV4
},
45 { .name
= "net6", .code
= P_NET6
, .type
= LTTNG_TCP
, .dtype
= LTTNG_DST_IPV6
},
46 { .name
= "tcp", .code
= P_TCP
, .type
= LTTNG_TCP
, .dtype
= LTTNG_DST_IPV4
},
47 { .name
= "tcp6", .code
= P_TCP6
, .type
= LTTNG_TCP
, .dtype
= LTTNG_DST_IPV6
},
52 * Validate if proto is a supported protocol from proto_uri array.
54 static const struct uri_proto
*validate_protocol(char *proto
)
56 const struct uri_proto
*supported
;
63 for (supported
= &proto_uri
[0];
64 supported
->name
!= NULL
; ++supported
) {
65 if (strncmp(proto
, supported
->name
, strlen(proto
)) == 0) {
80 * Return 0 if equal else 1.
82 int uri_compare(struct lttng_uri
*uri1
, struct lttng_uri
*uri2
)
84 return memcmp(uri1
, uri2
, sizeof(struct lttng_uri
));
90 void uri_free(struct lttng_uri
*uri
)
99 * Return an allocated URI.
101 struct lttng_uri
*uri_create(void)
103 struct lttng_uri
*uri
;
105 uri
= zmalloc(sizeof(struct lttng_uri
));
107 PERROR("zmalloc uri");
113 static int set_ip_address(const char *addr
, int af
, char *dst
, size_t size
)
116 unsigned char buf
[sizeof(struct in6_addr
)];
117 struct hostent
*record
;
119 /* Network protocol */
120 ret
= inet_pton(af
, addr
, buf
);
122 /* We consider the dst to be an hostname or an invalid IP char */
123 record
= gethostbyname2(addr
, af
);
124 if (record
== NULL
) {
125 /* At this point, the IP or the hostname is bad */
126 printf("bad hostname\n");
130 /* Translate IP to string */
131 (void) inet_ntop(af
, record
->h_addr_list
[0], dst
, size
);
133 memcpy(dst
, addr
, size
);
142 ssize_t
uri_parse(const char *str_uri
, struct lttng_uri
**uris
)
145 /* Size of the uris array. Default is 1 */
147 char net
[6], dst
[LTTNG_MAX_DNNAME
+ 1];
148 unsigned int ctrl_port
= 0;
149 unsigned int data_port
= 0;
150 struct lttng_uri
*uri
;
151 const struct uri_proto
*proto
;
154 * The first part is the protocol portion of a maximum of 5 bytes for now.
155 * The second part is the hostname or IP address. The 255 bytes size is the
156 * limit found in the RFC 1035 for the total length of a domain name
157 * (https://www.ietf.org/rfc/rfc1035.txt). Finally, for the net://
158 * protocol, two ports CAN be specified.
161 ret
= sscanf(str_uri
, "%5[^:]://", net
);
163 printf("bad protocol\n");
167 DBG3("URI protocol : %s", str_uri
);
169 proto
= validate_protocol(net
);
171 printf("no protocol\n");
176 if (proto
->code
== P_NET
|| proto
->code
== P_NET6
) {
177 /* Special case for net:// which requires two URI object */
181 /* Parse the rest of the URI */
182 ret
= sscanf(str_uri
+ strlen(net
), "://%255[^:]:%u:%u", dst
,
183 &ctrl_port
, &data_port
);
189 /* We have enough valid information to create URI(s) object */
191 /* Allocate URI array */
192 uri
= zmalloc(sizeof(struct lttng_uri
) * size
);
194 PERROR("zmalloc uri");
198 /* Copy generic information */
199 uri
[0].dtype
= proto
->dtype
;
200 uri
[0].proto
= proto
->type
;
201 uri
[0].port
= ctrl_port
;
203 DBG3("URI dtype: %d, proto: %d, port: %d", proto
->dtype
, proto
->type
,
206 switch (proto
->code
) {
208 memcpy(uri
[0].dst
.path
, dst
, sizeof(uri
[0].dst
.path
));
209 /* Reset port for the file:// URI */
211 DBG3("URI file destination: %s", dst
);
214 ret
= set_ip_address(dst
, AF_INET
, uri
[0].dst
.ipv4
,
215 sizeof(uri
[0].dst
.ipv4
));
220 memcpy(uri
[1].dst
.ipv4
, uri
[0].dst
.ipv4
, sizeof(uri
[1].dst
.ipv4
));
222 uri
[1].dtype
= proto
->dtype
;
223 uri
[1].proto
= proto
->type
;
224 uri
[1].port
= data_port
;
227 ret
= set_ip_address(dst
, AF_INET6
, uri
[0].dst
.ipv6
,
228 sizeof(uri
[0].dst
.ipv6
));
233 memcpy(uri
[1].dst
.ipv6
, uri
[0].dst
.ipv6
, sizeof(uri
[1].dst
.ipv6
));
235 uri
[1].dtype
= proto
->dtype
;
236 uri
[1].proto
= proto
->type
;
237 uri
[1].port
= data_port
;
240 ret
= set_ip_address(dst
, AF_INET
, uri
[0].dst
.ipv4
,
241 sizeof(uri
[0].dst
.ipv4
));
247 ret
= set_ip_address(dst
, AF_INET6
, uri
[0].dst
.ipv6
,
248 sizeof(uri
[0].dst
.ipv6
));
This page took 0.037089 seconds and 4 git commands to generate.