Skip to content

Commit e0d94ce

Browse files
authored
Merge pull request #70 from insa-unyte/feature/ipv6-support
Feature/ipv6 support
2 parents 742a62a + 2bace11 commit e0d94ce

File tree

11 files changed

+244
-84
lines changed

11 files changed

+244
-84
lines changed

README.md

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ Simple example of usage :
2828
#include <unyte-udp-notif/unyte_udp_utils.h>
2929
#include <unyte-udp-notif/unyte_udp_queue.h>
3030

31-
#define PORT 10001
31+
#define PORT "10001"
3232
#define ADDR "192.168.0.17"
3333

3434
int main()
@@ -61,9 +61,8 @@ int main()
6161
printf("unyte_udp_get_message_length: %u\n", unyte_udp_get_message_length(seg));
6262
printf("unyte_udp_get_generator_id: %u\n", unyte_udp_get_generator_id(seg));
6363
printf("unyte_udp_get_message_id: %u\n", unyte_udp_get_message_id(seg));
64-
printf("unyte_udp_get_src_port: %u\n", unyte_udp_get_src_port(seg));
65-
printf("unyte_udp_get_src_addr: %u\n", unyte_udp_get_src_addr(seg));
66-
printf("unyte_udp_get_dest_addr: %u\n", unyte_udp_get_dest_addr(seg));
64+
printf("unyte_udp_get_src[family]: %u\n", unyte_udp_get_src(seg)->ss_family); // AF_INET for IPv4 or AF_INET6 for IPv6
65+
printf("unyte_udp_get_dest_addr[family]: %u\n", unyte_udp_get_dest_addr(seg)->ss_family); // AF_INET for IPv4 or AF_INET6 for IPv6
6766
printf("unyte_udp_get_payload: %s\n", unyte_udp_get_payload(seg));
6867
printf("unyte_udp_get_payload_length: %u\n", unyte_udp_get_payload_length(seg));
6968

@@ -102,9 +101,8 @@ typedef struct unyte_segment_with_metadata
102101
- `uint16_t unyte_udp_get_message_length(unyte_seg_met_t *message);` : total length of the message within one UDP datagram, measured in octets, including the message header
103102
- `uint32_t unyte_udp_get_generator_id(unyte_seg_met_t *message);` : observation domain id of the message
104103
- `uint32_t unyte_udp_get_message_id(unyte_seg_met_t *message);` : message id of the message
105-
- `uint16_t unyte_udp_get_src_port(unyte_seg_met_t *message);` : source port of the message
106-
- `uint32_t unyte_udp_get_src_addr(unyte_seg_met_t *message);` : source address of the message
107-
- `uint32_t unyte_udp_get_dest_addr(unyte_seg_met_t *message);` : collector address
104+
- `struct sockaddr_storage * unyte_udp_get_src(unyte_seg_met_t *message);` : source IP and port of the message. Could be IPv4 or IPv6.
105+
- `struct sockaddr_storage * unyte_udp_get_dest_addr(unyte_seg_met_t *message);` : collector address. Could be IPv4 or IPv6.
108106
- `char *unyte_udp_get_payload(unyte_seg_met_t *message);` : payload buffer
109107
- `uint16_t unyte_udp_get_payload_length(unyte_seg_met_t *message);` : payload length
110108

@@ -115,7 +113,7 @@ To activate this thread, you must initiate the monitoring thread queue size (`mo
115113
typedef struct
116114
{
117115
char *address;
118-
uint16_t port;
116+
char *port;
119117
...
120118
uint monitoring_queue_size; // monitoring queue size if wanted to activate the monitoring thread. Default: 0. Recommended: 500.
121119
uint monitoring_delay; // monitoring queue frequence in seconds. Default: 5 seconds
@@ -163,7 +161,7 @@ Simple usage of the sender :
163161
#include <unyte-udp-notif/unyte_sender.h>
164162
#include <unyte-udp-notif/unyte_udp_utils.h>
165163

166-
#define PORT 10001
164+
#define PORT "10001"
167165
#define ADDR "192.168.0.17"
168166
#define MTU 1500
169167

examples/client_monitoring.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,12 @@ int main(int argc, char *argv[])
4545
// Initialize collector options
4646
unyte_udp_options_t options = {0};
4747
options.address = argv[1];
48-
options.port = atoi(argv[2]);
48+
options.port = argv[2];
4949
options.recvmmsg_vlen = USED_VLEN;
5050
options.monitoring_delay = 2;
5151
options.monitoring_queue_size = 500;
5252

53-
printf("Listening on %s:%d\n", options.address, options.port);
53+
printf("Listening on %s:%s\n", options.address, options.port);
5454

5555
/* Initialize collector */
5656
unyte_udp_collector_t *collector = unyte_udp_start_collector(&options);

examples/client_sample.c

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,15 @@
55
#include <string.h>
66
#include <signal.h>
77
#include <unistd.h>
8+
#include <arpa/inet.h>
89

910
#include "../src/hexdump.h"
1011
#include "../src/unyte_udp_collector.h"
1112
#include "../src/unyte_udp_utils.h"
1213
#include "../src/unyte_udp_queue.h"
1314

14-
#define USED_VLEN 10
15-
#define MAX_TO_RECEIVE 200
15+
#define USED_VLEN 1
16+
#define MAX_TO_RECEIVE 20
1617

1718
int main(int argc, char *argv[])
1819
{
@@ -27,8 +28,8 @@ int main(int argc, char *argv[])
2728
unyte_udp_options_t options = {0};
2829
options.recvmmsg_vlen = USED_VLEN;
2930
options.address = argv[1];
30-
options.port = atoi(argv[2]);
31-
printf("Listening on %s:%d\n", options.address, options.port);
31+
options.port = argv[2];
32+
printf("Listening on %s:%s\n", options.address, options.port);
3233

3334
/* Initialize collector */
3435
unyte_udp_collector_t *collector = unyte_udp_start_collector(&options);
@@ -53,9 +54,24 @@ int main(int argc, char *argv[])
5354
// printf("unyte_udp_get_message_length: %u\n", unyte_udp_get_message_length(seg));
5455
// printf("unyte_udp_get_generator_id: %u\n", unyte_udp_get_generator_id(seg));
5556
// printf("unyte_udp_get_message_id: %u\n", unyte_udp_get_message_id(seg));
56-
// printf("unyte_udp_get_src_port: %u\n", unyte_udp_get_src_port(seg));
57-
// printf("unyte_udp_get_src_addr: %u\n", unyte_udp_get_src_addr(seg));
58-
// printf("unyte_udp_get_dest_addr: %u\n", unyte_udp_get_dest_addr(seg));
57+
// printf("unyte_udp_get_src[family]: %u\n", unyte_udp_get_src(seg)->ss_family);
58+
// printf("unyte_udp_get_dest_addr[family]: %u\n", unyte_udp_get_dest_addr(seg)->ss_family);
59+
// char ip_canonical[100];
60+
// if (unyte_udp_get_src(seg)->ss_family == AF_INET) {
61+
// printf("src IPv4: %s\n", inet_ntop(unyte_udp_get_src(seg)->ss_family, &((struct sockaddr_in*)unyte_udp_get_src(seg))->sin_addr.s_addr, ip_canonical, sizeof ip_canonical));
62+
// printf("src port: %u\n", ntohs(((struct sockaddr_in*)unyte_udp_get_src(seg))->sin_port));
63+
// } else {
64+
// printf("src IPv6: %s\n", inet_ntop(unyte_udp_get_src(seg)->ss_family, &((struct sockaddr_in6*)unyte_udp_get_src(seg))->sin6_addr.s6_addr, ip_canonical, sizeof ip_canonical));
65+
// printf("src port: %u\n", ntohs(((struct sockaddr_in6*)unyte_udp_get_src(seg))->sin6_port));
66+
// }
67+
// char ip_dest_canonical[100];
68+
// if (unyte_udp_get_src(seg)->ss_family == AF_INET) {
69+
// printf("dest IPv4: %s\n", inet_ntop(unyte_udp_get_dest_addr(seg)->ss_family, &((struct sockaddr_in*)unyte_udp_get_dest_addr(seg))->sin_addr.s_addr, ip_dest_canonical, sizeof ip_dest_canonical));
70+
// printf("dest port: %u\n", ntohs(((struct sockaddr_in*)unyte_udp_get_dest_addr(seg))->sin_port));
71+
// } else {
72+
// printf("dest IPv6: %s\n", inet_ntop(unyte_udp_get_dest_addr(seg)->ss_family, &((struct sockaddr_in6*)unyte_udp_get_dest_addr(seg))->sin6_addr.s6_addr, ip_dest_canonical, sizeof ip_dest_canonical));
73+
// printf("dest port: %u\n", ntohs(((struct sockaddr_in6*)unyte_udp_get_dest_addr(seg))->sin6_port));
74+
// }
5975
// printf("unyte_udp_get_payload: %s\n", unyte_udp_get_payload(seg));
6076
// printf("unyte_udp_get_payload_length: %u\n", unyte_udp_get_payload_length(seg));
6177

src/listening_worker.c

Lines changed: 52 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ void free_parsers(struct parse_worker *parsers, struct listener_thread_input *in
5959
free(messages[i].msg_hdr.msg_iov->iov_base);
6060
free(messages[i].msg_hdr.msg_iov);
6161
free(messages[i].msg_hdr.msg_name);
62+
free(messages[i].msg_hdr.msg_control);
6263
}
6364
free(messages);
6465
}
@@ -185,6 +186,45 @@ int create_monitoring_thread(struct monitoring_worker *monitoring, unyte_udp_que
185186
return 0;
186187
}
187188

189+
struct sockaddr_storage *get_dest_addr(struct msghdr *mh, unyte_udp_sock_t *sock)
190+
{
191+
struct sockaddr_storage *addr = (struct sockaddr_storage *)malloc(sizeof(struct sockaddr_storage));
192+
193+
if (addr == NULL)
194+
{
195+
printf("Malloc failed\n");
196+
return NULL;
197+
}
198+
199+
memset(addr, 0, sizeof(struct sockaddr_storage));
200+
struct in_pktinfo *in_pktinfo;
201+
struct in6_pktinfo *in6_pktinfo;
202+
203+
for ( // iterate through all the control headers
204+
struct cmsghdr *cmsg = CMSG_FIRSTHDR(mh);
205+
cmsg != NULL;
206+
cmsg = CMSG_NXTHDR(mh, cmsg))
207+
{
208+
if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO)
209+
{
210+
in_pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsg);
211+
((struct sockaddr_in *)addr)->sin_family = AF_INET;
212+
((struct sockaddr_in *)addr)->sin_addr = in_pktinfo->ipi_addr;
213+
((struct sockaddr_in *)addr)->sin_port = ((struct sockaddr_in *)sock->addr)->sin_port;
214+
break;
215+
}
216+
if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO)
217+
{
218+
in6_pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmsg);
219+
((struct sockaddr_in6 *)addr)->sin6_family = AF_INET6;
220+
((struct sockaddr_in6 *)addr)->sin6_addr = in6_pktinfo->ipi6_addr;
221+
((struct sockaddr_in6 *)addr)->sin6_port = ((struct sockaddr_in6 *)sock->addr)->sin6_port;
222+
break;
223+
}
224+
}
225+
return addr;
226+
}
227+
188228
/**
189229
* Udp listener worker on PORT port.
190230
*/
@@ -234,11 +274,14 @@ int listener(struct listener_thread_input *in)
234274
printf("Malloc failed \n");
235275
return -1;
236276
}
277+
int cmbuf_len = 1024;
237278
// Init msg_iov first to reduce mallocs every iteration of while
238279
for (uint16_t i = 0; i < in->recvmmsg_vlen; i++)
239280
{
240281
messages[i].msg_hdr.msg_iov = (struct iovec *)malloc(sizeof(struct iovec));
241282
messages[i].msg_hdr.msg_iovlen = 1;
283+
messages[i].msg_hdr.msg_control = (char *)malloc(cmbuf_len);
284+
messages[i].msg_hdr.msg_controllen = cmbuf_len;
242285
}
243286
// FIXME: malloc failed
244287
// TODO: malloc array of msg_hdr.msg_name and assign addresss to every messages[i]
@@ -251,12 +294,10 @@ int listener(struct listener_thread_input *in)
251294
{
252295
messages[i].msg_hdr.msg_iov->iov_base = (char *)malloc(UDP_SIZE * sizeof(char));
253296
messages[i].msg_hdr.msg_iov->iov_len = UDP_SIZE;
254-
messages[i].msg_hdr.msg_control = 0;
255-
messages[i].msg_hdr.msg_controllen = 0;
256-
messages[i].msg_hdr.msg_name = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in));
257-
messages[i].msg_hdr.msg_namelen = sizeof(struct sockaddr_in);
297+
memset(messages[i].msg_hdr.msg_control, 0, cmbuf_len);
298+
messages[i].msg_hdr.msg_name = (struct sockaddr_storage *)malloc(sizeof(struct sockaddr_storage));
299+
messages[i].msg_hdr.msg_namelen = sizeof(struct sockaddr_storage);
258300
}
259-
260301
int read_count = recvmmsg(*in->conn->sockfd, messages, in->recvmmsg_vlen, 0, NULL);
261302
if (read_count == -1)
262303
{
@@ -273,7 +314,12 @@ int listener(struct listener_thread_input *in)
273314
// If msg_len == 0 -> message has 0 bytes -> we discard message and free the buffer
274315
if (messages[i].msg_len > 0)
275316
{
276-
unyte_min_t *seg = minimal_parse(messages[i].msg_hdr.msg_iov->iov_base, ((struct sockaddr_in *)messages[i].msg_hdr.msg_name), in->conn->addr);
317+
struct sockaddr_storage *dest_addr = get_dest_addr(&(messages[i].msg_hdr), in->conn);
318+
319+
if (dest_addr == NULL)
320+
return -1;
321+
322+
unyte_min_t *seg = minimal_parse(messages[i].msg_hdr.msg_iov->iov_base, ((struct sockaddr_storage *)messages[i].msg_hdr.msg_name), dest_addr);
277323
if (seg == NULL)
278324
{
279325
printf("minimal_parse error\n");
@@ -303,11 +349,6 @@ int listener(struct listener_thread_input *in)
303349
free(messages[i].msg_hdr.msg_iov->iov_base);
304350
}
305351
}
306-
307-
for (uint16_t i = 0; i < in->recvmmsg_vlen; i++)
308-
{
309-
free(messages[i].msg_hdr.msg_name);
310-
}
311352
}
312353

313354
// Never called cause while(1)

src/listening_worker.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ struct listener_thread_input
1818
{
1919
unyte_udp_queue_t *output_queue; /* The queue used to push the segments outside. */
2020
unyte_udp_queue_t *monitoring_queue; /* The queue used to push monitoring stats of segments outside. */
21-
uint16_t port; /* The port to initialize the interface on. */
2221
unyte_udp_sock_t *conn; /* Connection with addr, sockfd */
2322
uint16_t recvmmsg_vlen; /* The recvmmsg buffer array size */
2423
uint nb_parsers; /* Number of parsers instances to init */

src/parsing_worker.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,17 @@ unyte_seg_met_t *create_assembled_msg(char *complete_msg, unyte_seg_met_t *src_p
3636
return NULL;
3737
}
3838

39+
parsed_msg->metadata->src = (struct sockaddr_storage *)malloc(sizeof(struct sockaddr_storage));
40+
parsed_msg->metadata->dest = (struct sockaddr_storage *)malloc(sizeof(struct sockaddr_storage));
41+
42+
if (parsed_msg->metadata->src == NULL || parsed_msg->metadata->dest == NULL)
43+
{
44+
free(parsed_msg->metadata);
45+
free(parsed_msg->header);
46+
free(parsed_msg);
47+
return NULL;
48+
}
49+
3950
copy_unyte_seg_met_headers(parsed_msg, src_parsed_segment);
4051

4152
// Rewrite header length and message length

src/unyte_sender.c

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,31 +4,45 @@
44
#include <unistd.h>
55
#include <netinet/in.h>
66
#include <arpa/inet.h>
7-
#include <linux/if.h>
87
#include <string.h>
98
#include "unyte_sender.h"
9+
#include <net/if.h>
1010

1111
struct unyte_sender_socket *unyte_start_sender(unyte_sender_options_t *options)
1212
{
13-
struct sockaddr_in *addr = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in));
13+
unyte_IP_type_t ip_type = get_IP_type(options->address);
14+
if (ip_type == unyte_UNKNOWN)
15+
{
16+
printf("Invalid IP address: %s\n", options->address);
17+
exit(EXIT_FAILURE);
18+
}
19+
20+
void *addr;
1421
struct unyte_sender_socket *sender_sk = (struct unyte_sender_socket *)malloc(sizeof(struct unyte_sender_socket));
22+
23+
if (ip_type == unyte_IPV4)
24+
addr = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in));
25+
else
26+
addr = (struct sockaddr_in6 *)malloc(sizeof(struct sockaddr_in6));
27+
1528
if (addr == NULL || sender_sk == NULL)
1629
{
1730
perror("Malloc failed.\n");
1831
exit(EXIT_FAILURE);
1932
}
2033

21-
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
34+
int sockfd;
35+
if (ip_type == unyte_IPV4)
36+
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
37+
else
38+
sockfd = socket(AF_INET6, SOCK_DGRAM, 0);
39+
2240
if (sockfd < 0)
2341
{
2442
perror("socket()");
2543
exit(EXIT_FAILURE);
2644
}
2745

28-
addr->sin_family = AF_INET;
29-
addr->sin_port = htons(options->port);
30-
inet_pton(AF_INET, options->address, &addr->sin_addr);
31-
3246
// Binding socket to an interface
3347
const char *interface = options->interface;
3448
if (options->interface != NULL && (strlen(interface) > 0))
@@ -57,10 +71,30 @@ struct unyte_sender_socket *unyte_start_sender(unyte_sender_options_t *options)
5771
exit(EXIT_FAILURE);
5872
}
5973

74+
int connect_ret = 0;
75+
if (ip_type == unyte_IPV4)
76+
{
77+
memset(addr, 0, sizeof(struct sockaddr_in));
78+
((struct sockaddr_in *)addr)->sin_family = AF_INET;
79+
((struct sockaddr_in *)addr)->sin_port = htons(options->port);
80+
inet_pton(AF_INET, options->address, &((struct sockaddr_in *)addr)->sin_addr);
81+
connect_ret = connect(sockfd, (struct sockaddr *)addr, sizeof(struct sockaddr_in));
82+
}
83+
else
84+
{
85+
memset(addr, 0, sizeof(struct sockaddr_in6));
86+
((struct sockaddr_in6 *)addr)->sin6_family = AF_INET6;
87+
((struct sockaddr_in6 *)addr)->sin6_port = htons(options->port);
88+
((struct sockaddr_in6 *)addr)->sin6_scope_id = if_nametoindex("eth0"); //TODO: check all interfaces or bind to one interface
89+
((struct sockaddr_in6 *)addr)->sin6_flowinfo = 0;
90+
inet_pton(AF_INET6, options->address, &((struct sockaddr_in6 *)addr)->sin6_addr);
91+
connect_ret = connect(sockfd, (struct sockaddr *)addr, sizeof(struct sockaddr_in6));
92+
}
93+
6094
// connect socket to destination address
61-
if (connect(sockfd, addr, sizeof(struct sockaddr_in)) == -1)
95+
if (connect_ret == -1)
6296
{
63-
perror("Bind failed");
97+
perror("Connect failed");
6498
close(sockfd);
6599
exit(EXIT_FAILURE);
66100
}

0 commit comments

Comments
 (0)