Commit 20178d10 authored by roel0's avatar roel0

Functional test

parent e46e6503
......@@ -204,6 +204,7 @@ endif
ifneq ($(MCAST),0)
include rules/mcast.mk
include rules/igmp.mk
include rules/mld.mk
endif
ifneq ($(NAT),0)
include rules/nat.mk
......@@ -333,7 +334,7 @@ units: mod core lib $(UNITS_OBJ) $(MOD_OBJ)
@echo -e "\n\t[UNIT TESTS SUITE]"
@mkdir -p $(PREFIX)/test
@echo -e "\t[CC] units.o"
@$(CC) -c -o $(PREFIX)/test/units.o test/units.c $(CFLAGS) -I stack -I modules -I includes -I test/unit -DUNIT_TEST
@$(CC) -g -c -o $(PREFIX)/test/units.o test/units.c $(CFLAGS) -I stack -I modules -I includes -I test/unit -DUNIT_TEST
@echo -e "\t[LD] $(PREFIX)/test/units"
@$(CC) -o $(PREFIX)/test/units $(CFLAGS) $(PREFIX)/test/units.o -lcheck -lm -pthread -lrt \
$(UNITS_OBJ) $(PREFIX)/modules/pico_aodv.o \
......
......@@ -15,7 +15,7 @@
#include "pico_stack.h"
#include "pico_tree.h"
#include "pico_socket.h"
#include "pico_mld.h"
#define icmp6_dbg(...) do {} while(0)
/* #define icmp6_dbg dbg */
......@@ -105,7 +105,14 @@ static int pico_icmp6_process_in(struct pico_protocol *self, struct pico_frame *
#endif
pico_frame_discard(f);
break;
#ifdef PICO_SUPPORT_MCAST
case PICO_MLD_QUERY:
case PICO_MLD_REPORT:
case PICO_MLD_DONE:
case PICO_MLD_REPORTV2:
pico_mld_process_in(f);
break;
#endif
default:
return pico_ipv6_nd_recv(f); /* CAUTION -- Implies: pico_frame_discard in any case, keep in the default! */
}
......
......@@ -9,7 +9,7 @@
#define _INCLUDE_PICO_ICMP6
#include "pico_addressing.h"
#include "pico_protocol.h"
#include "pico_mld.h"
/* ICMP header sizes */
#define PICO_ICMP6HDR_DRY_SIZE 4
#define PICO_ICMP6HDR_ECHO_REQUEST_SIZE 8
......@@ -167,6 +167,16 @@ PACKED_STRUCT_DEF pico_icmp6_hdr {
struct pico_ip6 dest;
uint8_t options[0];
} redirect;
PEDANTIC_STRUCT_DEF mld_s {
uint16_t max_resp_time;
uint16_t reserved;
struct pico_ip6 mmcast_group;
/*MLDv2*/
uint8_t reserverd; // With S and QRV
uint8_t QQIC;
uint16_t nbr_src;
struct pico_ip6 src[0];
} mld;
} info;
} msg;
};
......
......@@ -577,7 +577,7 @@ struct pico_protocol pico_proto_igmp = {
.q_out = &igmp_out,
};
int pico_igmp_state_change(struct pico_ip4 *mcast_link, struct pico_ip4 *mcast_group, uint8_t filter_mode, struct pico_tree *MCASTFilter, uint8_t state)
int pico_igmp_state_change(struct pico_ip4 *mcast_link, struct pico_ip4 *mcast_group, uint8_t filter_mode, struct pico_tree *_MCASTFilter, uint8_t state)
{
struct igmp_parameters *p = NULL;
......@@ -623,7 +623,7 @@ int pico_igmp_state_change(struct pico_ip4 *mcast_link, struct pico_ip4 *mcast_g
return -1;
}
p->filter_mode = filter_mode;
p->MCASTFilter = MCASTFilter;
p->MCASTFilter = _MCASTFilter;
return pico_igmp_process_event(p);
}
......
......@@ -22,5 +22,5 @@
extern struct pico_protocol pico_proto_igmp;
int pico_igmp_state_change(struct pico_ip4 *mcast_link, struct pico_ip4 *mcast_group, uint8_t filter_mode, struct pico_tree *MCASTFilter, uint8_t state);
int pico_igmp_state_change(struct pico_ip4 *mcast_link, struct pico_ip4 *mcast_group, uint8_t filter_mode, struct pico_tree *_MCASTFilter, uint8_t state);
#endif /* _INCLUDE_PICO_IGMP */
This diff is collapsed.
......@@ -13,7 +13,7 @@
#define PICO_SIZE_IP6HDR ((uint32_t)(sizeof(struct pico_ipv6_hdr)))
#define PICO_IPV6_DEFAULT_HOP 64
#define PICO_IPV6_MIN_MTU 1280
#define PICO_IPV6_STRING 45
#define PICO_IPV6_EXTHDR_HOPBYHOP 0
#define PICO_IPV6_EXTHDR_ROUTING 43
......@@ -59,6 +59,12 @@ struct pico_ipv6_link
struct pico_timer *dad_timer;
uint16_t dup_detect_retrans;
pico_time expire_time;
#ifdef PICO_SUPPORT_MCAST
struct pico_tree *MCASTGroups;
uint8_t mcast_compatibility;
uint8_t mcast_last_query_interval;
#endif
};
union pico_link {
struct pico_ipv4_link ipv4;
......@@ -70,7 +76,14 @@ struct pico_ipv6_hbhoption {
uint8_t len;
uint8_t options[0];
};
#ifdef PICO_SUPPORT_MCAST
struct pico_ipv6_mcast_group {
uint8_t filter_mode;
uint16_t reference_count;
struct pico_ip6 mcast_addr;
struct pico_tree MCASTSources;
};
#endif
struct pico_ipv6_destoption {
uint8_t type;
uint8_t len;
......@@ -154,4 +167,11 @@ void pico_ipv6_check_lifetime_expired(pico_time now, void *arg);
int pico_ipv6_dev_routing_enable(struct pico_device *dev);
int pico_ipv6_dev_routing_disable(struct pico_device *dev);
void pico_ipv6_router_down(struct pico_ip6 *address);
int pico_ipv6_mcast_join(struct pico_ip6 *mcast_link, struct pico_ip6 *mcast_group, uint8_t reference_count, uint8_t filter_mode, struct pico_tree *_MCASTFilter);
int pico_ipv6_mcast_leave(struct pico_ip6 *mcast_link, struct pico_ip6 *mcast_group, uint8_t reference_count, uint8_t filter_mode, struct pico_tree *_MCASTFilter);
struct pico_ipv6_link *pico_ipv6_get_default_mcastlink(void);
int pico_ipv6_is_null_address(struct pico_ip6 * ip6);
#endif
This diff is collapsed.
/*********************************************************************
PicoTCP. Copyright (c) 2012 TASS Belgium NV. Some rights reserved.
See LICENSE and COPYING for usage.
.
Authors: Roel Postelmans
*********************************************************************/
#ifndef INCLUDE_PICO_MLD
#define INCLUDE_PICO_MLD
#define PICO_MLDV1 1
#define PICO_MLDV2 2
#define PICO_MLD_QUERY 130
#define PICO_MLD_REPORT 131
#define PICO_MLD_DONE 132
#define PICO_MLD_REPORTV2 143
/*RFC 3810 $6.2 */
#define MLD_HOP_LIMIT 1
/* states */
#define MLD_STATE_NON_LISTENER (0x0)
#define MLD_STATE_DELAYING_LISTENER (0x1)
#define MLD_STATE_IDLE_LISTENER (0x2)
#define PICO_MLD_STATE_CREATE 1
#define PICO_MLD_STATE_UPDATE 2
#define PICO_MLD_STATE_DELETE 3
/* group record types */
#define MLD_MODE_IS_INCLUDE (1)
#define MLD_MODE_IS_EXCLUDE (2)
#define MLD_CHANGE_TO_INCLUDE_MODE (3)
#define MLD_CHANGE_TO_EXCLUDE_MODE (4)
/* events */
#define MLD_EVENT_QUERY_RECV (0x0)
#define MLD_EVENT_DONE_RECV (0x1)
#define MLD_EVENT_REPORT_RECV (0x2)
#define MLD_EVENT_TIMER_EXPIRED (0x3)
#define MLD_EVENT_STOP_LISTENING (0x4)
#define MLD_EVENT_START_LISTENING (0x5)
#define MLD_EVENT_DELETE_GROUP (0x0)
#define MLD_EVENT_CREATE_GROUP (0x1)
#define MLD_EVENT_UPDATE_GROUP (0x2)
#define MLD_EVENT_QUERY_RECV (0x3)
#define MLD_EVENT_REPORT_RECV (0x4)
#define MLD_EVENT_TIMER_EXPIRED (0x5)
/* (default) Variabels for times/counters */
/* ALL IN SECONDS */
#define MLD_ROBUSTNESS (2)
#define MLD_QUERY_INTERVAL (125)
#define MLD_QUERY_RESPONSE_INTERVAL (10)
#define MLD_DEFAULT_MAX_RESPONSE_TIME (100)
#define MLD_MULTICAST_LISTENER_INTERVAL (MLD_ROBUSTNESS * MLD_QUERY_INTERVAL) + MLD_QUERY_RESPONSE_INTERVAL
#define MLD_OTHER_QUERIER_PRESENT_INTERVAL (MLD_ROBUSTNESS * MLD_QUERY_INTERVAL) + (0.5 * MLD_QUERY_RESPONSE_INTERVAL)
#define MLD_STARTUP_QUERY_INTERVAL (0.25 * MLD_QUERY_INTERVAL)
#define MLD_STARTUP_QUERY_COUNT MLD_ROBUSTNESS
#define MLD_LAST_LISTENER_QUERY_INTERVAL 1
#define MLD_LISTENER_QUERY_COUNT MLD_ROBUSTNESS
#define MLD_UNSOLICITED_REPORT_INTERVAL 10
/* custom timers types */
#define MLD_TIMER_GROUP_REPORT (1)
#define MLD_TIMER_V1_REPORT (2)
#define MLD_TIMER_V2_REPORT (3)
/* Who has send the last report message */
#define MLD_HOST_LAST (0x1)
#define MLD_HOST_NOT_LAST (0x0)
#define IP_OPTION_ROUTER_ALERT_LEN (8)
extern struct pico_protocol pico_proto_mld;
struct mld_multicast_address_record {
uint8_t type;
uint8_t aux_len;
uint16_t nbr_src;
struct pico_ip6 multicast;
struct pico_ip6 src[0];
};
struct mld_parameters {
uint8_t event;
uint8_t state;
uint8_t general_query;
uint8_t filter_mode;
uint8_t last_host;
uint8_t max_resp_time;
struct pico_ip6 mcast_link;
struct pico_ip6 mcast_group;
struct pico_tree *MCASTFilter;
struct pico_frame *f;
};
struct mld_timer {
uint8_t type;
uint8_t stopped;
pico_time start;
pico_time delay;
struct pico_ip6 mcast_link;
struct pico_ip6 mcast_group;
struct pico_frame *f;
void (*mld_callback)(struct mld_timer *t);
};
int pico_mld_process_in(struct pico_frame *f);
int pico_mld_state_change(struct pico_ip6 *mcast_link, struct pico_ip6 *mcast_group, uint8_t filter_mode, struct pico_tree *_MCASTFilter, uint8_t state);
#endif /* _INCLUDE_PICO_MLD */
OPTIONS+=-DPICO_SUPPORT_MLD
MOD_OBJ+=$(LIBBASE)modules/pico_mld.o
......@@ -1516,7 +1516,6 @@ int pico_socket_bind(struct pico_socket *s, void *local_addr, uint16_t *port)
return -1;
}
/* When given port = 0, get a random high port to bind to. */
if (*port == 0) {
*port = pico_socket_high_port(PROTO(s));
......
This diff is collapsed.
......@@ -134,9 +134,11 @@ void *pico_tree_insert_implementation(struct pico_tree*tree, void *key, uint8_t
int result = 0;
LocalKey = (IS_NOT_LEAF(tree->root) ? pico_tree_findKey(tree, key) : NULL);
/* if node already in, bail out */
if(LocalKey)
if(LocalKey) {
return LocalKey;
}
else
{
if(allocator == USE_PICO_PAGE0_ZALLOC)
......@@ -207,7 +209,6 @@ void *pico_tree_findKey(struct pico_tree *tree, void *key)
found = tree->root;
while(IS_NOT_LEAF(found))
{
int result;
......@@ -299,9 +300,8 @@ void *pico_tree_delete(struct pico_tree *tree, void *key)
static inline void if_nodecolor_black_fix_collisions(struct pico_tree *tree, struct pico_tree_node *temp, uint8_t nodeColor)
{
/* deleted node is black, this will mess up the black path property */
if(nodeColor == BLACK)
if(nodeColor == BLACK)
fix_delete_collisions(tree, temp);
}
void *pico_tree_delete_implementation(struct pico_tree *tree, void *key, uint8_t allocator)
......@@ -310,16 +310,14 @@ void *pico_tree_delete_implementation(struct pico_tree *tree, void *key, uint8_t
uint8_t nodeColor; /* keeps the color of the node to be deleted */
void *lkey; /* keeps a copy of the key which will be removed */
struct pico_tree_node *delete; /* keeps a copy of the node to be extracted */
if (!key)
return NULL;
delete = pico_tree_findNode(tree, key);
/* this key isn't in the tree, bail out */
if(!delete)
if(!delete)
return NULL;
lkey = delete->keyValue;
nodeColor = pico_tree_delete_check_switch(tree, delete, &temp);
......
......@@ -6,17 +6,17 @@ TFTP_WORK_SUBDIR="${TFTP_WORK_DIR}/subdir"
TFTP_WORK_FILE="test.img"
function tftp_setup() {
dd if=/dev/urandom bs=1000 count=10 of=${1}/$TFTP_WORK_FILE
dd if=/dev/urandom bs=1000 count=10 of=${1}/$TFTP_WORK_FILE
}
function tftp_cleanup() {
echo CLEANUP
pwd;ls
killall -w picoapp.elf
rm -rf $TFTP_WORK_DIR
if [ $1 ]; then
exit $1
fi
echo CLEANUP
pwd;ls
killall -w picoapp.elf
rm -rf $TFTP_WORK_DIR
if [ $1 ]; then
exit $1
fi
}
......@@ -91,6 +91,21 @@ echo
echo
echo
echo "MULTICAST IPV6 TEST"
(./build/test/picoapp6.elf --vde pic1,/tmp/pic0.ctl,fe80::a28:3,ffff::, -a mcastreceive_ipv6,fe80::a28:3,ff00::e007:707,6667,6667,) &
(./build/test/picoapp6.elf --vde pic2,/tmp/pic0.ctl,fe80::a28:4,ffff::, -a mcastreceive_ipv6,fe80::a28:4,ff00::e007:707,6667,6667,) &
(./build/test/picoapp6.elf --vde pic3,/tmp/pic0.ctl,fe80::a28:5,ffff::, -a mcastreceive_ipv6,fe80::a28:5,ff00::e007:707,6667,6667,) &
sleep 2
./build/test/picoapp6.elf --vde pic0,/tmp/pic0.ctl,fe80::a28:2,ffff::, -a mcastsend_ipv6,fe80::a28:2,ff00::e007:707,6667,6667, || exit 1
(wait && wait && wait) || exit 1
echo
echo
echo
echo
echo
echo "IPV4 tests!"
echo "PING LOCALHOST"
......@@ -100,7 +115,6 @@ echo "PING TEST"
(./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.8:255.255.0.0:::) &
./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.9:255.255.0.0::: -a ping:10.40.0.8:: || exit 1
killall -w picoapp.elf
echo "PING TEST -- Aborted in 4 seconds"
(./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.8:255.255.0.0:::) &
(./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.9:255.255.0.0::: -a ping:10.40.0.8:4:) &
......
......@@ -14,7 +14,9 @@ $(PREFIX)/examples/dns_sd.o \
$(PREFIX)/examples/dnsclient.o \
$(PREFIX)/examples/mdns.o \
$(PREFIX)/examples/multicast_recv.o \
$(PREFIX)/examples/multicast_ip6_recv.o \
$(PREFIX)/examples/multicast_send.o \
$(PREFIX)/examples/multicast_ip6_send.o \
$(PREFIX)/examples/natbox.o \
$(PREFIX)/examples/noop.o \
$(PREFIX)/examples/ping.o \
......
#include "utils.h"
#include <pico_socket.h>
/*** START Multicast RECEIVE + ECHO ***/
/*
* multicast receive expects the following format: mcastreceive:link_addr:mcast_addr:listen_port:sendto_port
* link_addr: mcastreceive picoapp IP address
* mcast_addr: multicast IP address to receive
* listen_port: port number on which the mcastreceive listens
* sendto_port: port number to echo multicast traffic to (echo to originating IP address)
*
* f.e.: ./build/test/picoapp.elf --vde pic1:/tmp/pic0.ctl:10.40.0.3:255.255.0.0: -a mcastreceive:10.40.0.3:224.7.7.7:6667:6667
*/
extern struct udpclient_pas *udpclient_pas;
extern struct udpecho_pas *udpecho_pas;
#ifdef PICO_SUPPORT_MCAST
void app_mcastreceive_ipv6(char *arg)
{
char *new_arg = NULL, *p = NULL, *nxt = arg;
char *laddr = NULL, *maddr = NULL, *lport = NULL, *sport = NULL;
uint16_t listen_port = 0;
struct pico_ip6 inaddr_link = {
0
}, inaddr_mcast = {
0
}, src[5] = {
{ 0xfe, 0x80, 0x00, 0x00, 0x00, 0, 0, 0, 0, 0, 0, 0, 0xac, 0x10, 0x01, 0 },
{ 0xfe, 0x80, 0x00, 0x00, 0x00, 0, 0, 0, 0, 0, 0, 0, 0xac, 0x10, 0x01, 0x10 },
{ 0xfe, 0x80, 0x00, 0x00, 0x00, 0, 0, 0, 0, 0, 0, 0, 0xac, 0x10, 0x01, 1 },
{ 0xff, 0x00, 0x00, 0x00, 0x00, 0, 0, 0, 0, 0, 0, 0, 0xe0, 0x01, 0x01, 1 },
};
struct pico_ipv6_mreq mreq = ZERO_MREQ_IP6;
struct pico_ipv6_mreq_source mreq_source = ZERO_MREQ_SRC_IP6;
/* start of parameter parsing */
if (nxt) {
nxt = cpy_arg(&laddr, nxt);
if (laddr) {
pico_string_to_ipv6(laddr, &inaddr_link.addr);
} else {
goto out;
}
} else {
/* no arguments */
goto out;
}
if (nxt) {
nxt = cpy_arg(&maddr, nxt);
if (maddr) {
pico_string_to_ipv6(maddr, &inaddr_mcast.addr);
} else {
goto out;
}
} else {
/* missing multicast address */
goto out;
}
if (nxt) {
nxt = cpy_arg(&lport, nxt);
if (lport && atoi(lport)) {
listen_port = short_be(atoi(lport));
} else {
/* incorrect listen_port */
goto out;
}
} else {
/* missing listen_port */
goto out;
}
if (nxt) {
nxt = cpy_arg(&sport, nxt);
if (sport && atoi(sport)) {
/* unused at this moment */
/* send_port = short_be(atoi(sport)); */
} else {
/* incorrect send_port */
goto out;
}
} else {
/* missing send_port */
goto out;
}
/* end of parameter parsing */
printf("\n%s: multicast receive started. Receiving packets on [%s]:%d\n\n", __FUNCTION__, maddr, short_be(listen_port));
/* udpecho:bind_addr:listen_port[:sendto_port:datasize] */
new_arg = calloc(1, strlen(laddr) + 1 + strlen(lport) + 1 + strlen(sport) + strlen(",64:") + 1);
p = strcat(new_arg, laddr);
p = strcat(p + strlen(laddr), ",");
p = strcat(p + 1, lport);
p = strcat(p + strlen(lport), ",");
p = strcat(p + 1, sport);
p = strcat(p + strlen(sport), ",64,");
app_udpecho(new_arg);
memcpy(&mreq.mcast_group_addr, &inaddr_mcast,sizeof(struct pico_ip6));
memcpy( &mreq_source.mcast_group_addr, &inaddr_mcast,sizeof(struct pico_ip6));
memcpy(&mreq.mcast_link_addr ,&inaddr_link, sizeof(struct pico_ip6));
memcpy(&mreq_source.mcast_link_addr ,&inaddr_link, sizeof(struct pico_ip6));
memcpy(&mreq_source.mcast_source_addr, &src[0], sizeof(struct pico_ip6));
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_ADD_MEMBERSHIP, &mreq) < 0) {
printf("%s: socket_setoption PICO_IP_ADD_MEMBERSHIP failed: %s\n", __FUNCTION__, strerror(pico_err));
}
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_DROP_MEMBERSHIP, &mreq) < 0) {
printf("%s: socket_setoption PICO_IP_DROP_MEMBERSHIP failed: %s\n", __FUNCTION__, strerror(pico_err));
}
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_ADD_MEMBERSHIP, &mreq) < 0) {
printf("%s: socket_setoption PICO_IP_ADD_MEMBERSHIP failed: %s\n", __FUNCTION__, strerror(pico_err));
}
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_BLOCK_SOURCE, &mreq_source) < 0) {
printf("%s: socket_setoption PICO_IP_BLOCK_SOURCE failed: %s\n", __FUNCTION__, strerror(pico_err));
}
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_UNBLOCK_SOURCE, &mreq_source) < 0) {
printf("%s: socket_setoption PICO_IP_UNBLOCK_SOURCE failed: %s\n", __FUNCTION__, strerror(pico_err));
}
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_DROP_MEMBERSHIP, &mreq) < 0) {
printf("%s: socket_setoption PICO_IP_DROP_MEMBERSHIP failed: %s\n", __FUNCTION__, strerror(pico_err));
}
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source) < 0) {
printf("%s: socket_setoption PICO_IP_ADD_SOURCE_MEMBERSHIP: %s\n", __FUNCTION__, strerror(pico_err));
}
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source) < 0) {
printf("%s: socket_setoption PICO_IP_DROP_SOURCE_MEMBERSHIP: %s\n", __FUNCTION__, strerror(pico_err));
}
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source) < 0) {
printf("%s: socket_setoption PICO_IP_ADD_SOURCE_MEMBERSHIP: %s\n", __FUNCTION__, strerror(pico_err));
}
memcpy(&mreq_source.mcast_source_addr, &src[1],sizeof(struct pico_ip6));
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source) < 0) {
printf("%s: socket_setoption PICO_IP_ADD_SOURCE_MEMBERSHIP: %s\n", __FUNCTION__, strerror(pico_err));
}
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_DROP_MEMBERSHIP, &mreq) < 0) {
printf("%s: socket_setoption PICO_IP_DROP_MEMBERSHIP failed: %s\n", __FUNCTION__, strerror(pico_err));
}
memcpy(&mreq_source.mcast_source_addr, &src[2],sizeof(struct pico_ip6));
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source) < 0) {
printf("%s: socket_setoption PICO_IP_ADD_SOURCE_MEMBERSHIP: %s\n", __FUNCTION__, strerror(pico_err));
}
memcpy(&mreq_source.mcast_source_addr, &src[3],sizeof(struct pico_ip6));
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source) < 0) {
printf("%s: socket_setoption PICO_IP_ADD_SOURCE_MEMBERSHIP: %s\n", __FUNCTION__, strerror(pico_err));
}
return;
out:
fprintf(stderr, "mcastreceive expects the following format: mcastreceive:link_addr:mcast_addr:listen_port[:send_port]\n");
exit(255);
}
#else
void app_mcastreceive_ipv6(char *arg)
{
printf("ERROR: PICO_SUPPORT_MCAST disabled\n");
return;
}
#endif
/*** END Multicast RECEIVE + ECHO ***/
#include "utils.h"
#include <pico_socket.h>
/*** START Multicast SEND ***/
/*
* multicast send expects the following format: mcastsend:link_addr:mcast_addr:sendto_port:listen_port
* link_addr: mcastsend picoapp IP address
* mcast_addr: multicast IP address to send to
* sendto_port: port number to send multicast traffic to
* listen_port: port number on which the mcastsend can receive data
*
* f.e.: ./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.2:255.255.255.0: -a mcastsend:10.40.0.2:224.7.7.7:6667:6667
*/
extern struct udpclient_pas *udpclient_pas;
#ifdef PICO_SUPPORT_MCAST
void app_mcastsend_ipv6(char *arg)
{
char *maddr = NULL, *laddr = NULL, *lport = NULL, *sport = NULL;
uint16_t sendto_port = 0;
struct pico_ip6 inaddr_link = {
0
}, inaddr_mcast = {
0
};
char *new_arg = NULL, *p = NULL, *nxt = arg;
struct pico_ipv6_mreq mreq = ZERO_MREQ_IP6;
/* start of parameter parsing */
if (nxt) {
nxt = cpy_arg(&laddr, nxt);
if (laddr) {
pico_string_to_ipv6(laddr, &inaddr_link.addr);
} else {
goto out;
}
} else {
/* no arguments */
goto out;
}
if (nxt) {
nxt = cpy_arg(&maddr, nxt);
if (maddr) {
pico_string_to_ipv6(maddr, &inaddr_mcast.addr);
} else {
goto out;
}
} else {
/* missing multicast address */
goto out;
}
if (nxt) {
nxt = cpy_arg(&sport, nxt);
if (sport && atoi(sport)) {
sendto_port = short_be(atoi(sport));
} else {
/* incorrect send_port */
goto out;
}
} else {
/* missing send_port */
goto out;
}
if (nxt) {
nxt = cpy_arg(&lport, nxt);
if (lport && atoi(lport)) {
/* unused at this moment */
/* listen_port = short_be(atoi(lport)); */
} else {
/* incorrect listen_port */
goto out;
}
} else {
/* missing listen_port */
goto out;
}
picoapp_dbg("\n%s: mcastsend started. Sending packets to %s:%u\n\n", __FUNCTION__, maddr, short_be(sendto_port));
/* udpclient:dest_addr:sendto_port[:listen_port:datasize:loops:subloops] */
new_arg = calloc(1, strlen(maddr) + 1 + strlen(sport) + 1 + strlen(lport) + strlen(",64,10,5,") + 1);
p = strcat(new_arg, maddr);
p = strcat(p + strlen(maddr), ",");
p = strcat(p + 1, sport);
p = strcat(p + strlen(sport), ",");
p = strcat(p + 1, lport);
p = strcat(p + strlen(lport), ",64,10,5,");
app_udpclient(new_arg);
memcpy(&mreq.mcast_group_addr,&inaddr_mcast, sizeof(struct pico_ip6));
memcpy(&mreq.mcast_link_addr ,&inaddr_link, sizeof(struct pico_ip6));
if(pico_socket_setoption(udpclient_pas->s, PICO_IP_ADD_MEMBERSHIP, &mreq) < 0) {
picoapp_dbg("%s: socket_setoption PICO_IP_ADD_MEMBERSHIP failed: %s\n", __FUNCTION__, strerror(pico_err));
exit(1);
}
return;
out:
picoapp_dbg("mcastsend expects the following format: mcastsend:link_addr:mcast_addr:sendto_port:listen_port\n");
exit(255);
}
#else
void app_mcastsend_ipv6(char *arg)
{
picoapp_dbg("ERROR: PICO_SUPPORT_MCAST disabled\n");
return;
}
#endif
/*** END Multicast SEND ***/
......@@ -53,7 +53,7 @@ void ping_abort_timer(pico_time now, void *_id)
void app_ping(char *arg)
{
char *dest = NULL;
char *next, *abort;
char *next, *abort = NULL;
static int id;
int timeout = 0;
next = cpy_arg(&dest, arg);
......@@ -61,7 +61,6 @@ void app_ping(char *arg)
fprintf(stderr, "ping needs the following format: ping:dst_addr:[abort after N sec]\n");
exit(255);
}
if (next) {
next = cpy_arg(&abort, next);
if (strlen(abort) > 0) {
......@@ -75,10 +74,9 @@ void app_ping(char *arg)
printf("Aborting ping after %d seconds\n", timeout);
}
}
if (!IPV6_MODE)
if (!IPV6_MODE) {
id = pico_icmp4_ping(dest, NUM_PING, 1000, 10000, 64, cb_ping);
}
#ifdef PICO_SUPPORT_IPV6
else
id = pico_icmp6_ping(dest, NUM_PING, 1000, 10000, 64, cb_ping6, NULL);
......@@ -87,7 +85,6 @@ void app_ping(char *arg)
printf("Adding abort timer after %d seconds for id %d\n", timeout, id);
pico_timer_add(timeout * 1000, ping_abort_timer, &id);
}
/* free copied args */
if (dest)
free(dest);
......
......@@ -230,7 +230,7 @@ void app_udpclient(char *arg)
ret = pico_socket_connect(udpclient_pas->s, &udpclient_pas->dst.ip6, udpclient_pas->sport);
if (ret < 0) {
printf("%s: error connecting to %s:%u: %s\n", __FUNCTION__, daddr, short_be(udpclient_pas->sport), strerror(pico_err));
printf("%s: error connecting to [%s]:%u: %s\n", __FUNCTION__, daddr, short_be(udpclient_pas->sport), strerror(pico_err));
free(udpclient_pas);
exit(1);
}
......