Beispiel #1
0
int
main(int argc, char *argv[])
{
    struct sol_oic_client client;
    struct sol_network_link_addr cliaddr = { .family = AF_INET, .port = 5683 };
    const char *resource_type;

    sol_init();

    if (inet_pton(cliaddr.family, "224.0.1.187", &cliaddr.addr) < 0) {
        printf("could not convert multicast ip address to sockaddr_in\n");
        return 1;
    }

    client.server = sol_coap_server_new(0);

    if (argc < 2) {
        printf("No rt filter specified, assuming everything\n");
        resource_type = NULL;
    } else {
        printf("Finding resources with resource type %s\n", argv[1]);
        resource_type = argv[1];
    }

    sol_oic_client_find_resource(&client, &cliaddr, resource_type, found_resource, NULL);

    sol_run();

    return 0;
}
Beispiel #2
0
int
main(int argc, char *argv[])
{
    struct sol_mqtt *mqtt;
    int port;

    sol_init();

    if (argc < 4) {
        SOL_INF("Usage: %s <ip> <port> <topic>", argv[0]);
        return 0;
    }

    port = atoi(argv[2]);
    topic = argv[3];

    mqtt = sol_mqtt_connect(argv[1], port, &config, NULL);
    if (!mqtt) {
        SOL_WRN("Unable to create MQTT session");
        return -1;
    }

    sol_run();

    sol_mqtt_disconnect(mqtt);

    sol_shutdown();

    return 0;
}
Beispiel #3
0
int
TEST_MAINLOOP_MAIN_FN(int argc, char *argv[])
{
    int err, i;
    struct sol_timeout *timeout_to_del;
    struct sol_idle *idler_to_del;

    err = sol_init();
    ASSERT(!err);

    timeout_to_del = sol_timeout_add(100, timeout_never_called, NULL);
    sol_timeout_add(20, on_timeout_del_and_new, timeout_to_del);

    sol_timeout_add(1, on_timeout_renew_twice, NULL);
    sol_idle_add(on_idler_renew_twice, NULL);

    for (i = 0; i < 5; i++)
        sol_idle_add(on_idler, (void *)(intptr_t)i);

    sol_idle_add(on_idler_del_another, &idler_to_del);
    idler_to_del = sol_idle_add(on_idler_never_called, NULL);

    sol_run();
    ASSERT_INT_EQ(timeout_called, 3);
    ASSERT_INT_EQ(timeout_renewed, 2);
    ASSERT_INT_EQ(idler_renewed, 2);

    for (i = 0; i < 10; i++)
        ASSERT_INT_EQ(idler_sequence[i], i);

    sol_shutdown();

    return 0;
}
Beispiel #4
0
int
test_main(struct test *start, struct test *stop, void (*reset_func)(void), int argc, char *argv[])
{
    const struct test *t;
    const char *pattern = NULL;
    int err, count = 0;

    err = sol_init();
    ASSERT(!err);

    if (argc > 1) {
        pattern = argv[1];
        printf("Running only tests that match '%s'\n", pattern);
    }

    for (t = start; t < stop; t++) {
        if (!pattern || strstr(t->name, pattern)) {
            printf("- %s\n", t->name);
            t->func();
            if (reset_func)
                reset_func();
            count++;
        }
    }

    if (count == 0) {
        printf("No tests found!\n");
        return EXIT_FAILURE;
    }

    sol_shutdown();
    printf("OK!\n");

    return 0;
}
int
main(int argc, char *argv[])
{
    int err;

    err = sol_init();
    ASSERT(!err);

    sol_idle_add(perform_tests, NULL);

    sol_run();

    sol_shutdown();

    return 0;
}
Beispiel #6
0
int
main(int argc, char *argv[])
{
    struct light_context context = { .resource = &light };
    struct sol_coap_server *server;
    char old_led_state;
    struct sol_network_link_addr servaddr = { .family = SOL_NETWORK_FAMILY_INET6,
                                              .port = DEFAULT_UDP_PORT };

    sol_init();

    server = sol_coap_server_new(&servaddr);
    if (!server) {
        SOL_WRN("Could not create a coap server using port %d.", DEFAULT_UDP_PORT);
        return -1;
    }

    if (sol_coap_server_register_resource(server, &light, NULL) < 0) {
        SOL_WRN("Could not register light resource");
        return -1;
    }

    console_fd = open("/dev/console", O_RDWR);
    if (console_fd < 0) {
        perror("Could not open '/dev/console'");
        return -1;
    }

    if (ioctl(console_fd, KDGETLED, (char *)&old_led_state)) {
        perror("Could not get the keyboard leds state");
        return -1;
    }

    context.server = server;
    sol_timeout_add(5000, update_light, &context);

    sol_run();

    sol_coap_server_unref(server);

    if (ioctl(console_fd, KDSETLED, old_led_state)) {
        perror("Could not return the leds to the old state");
        return -1;
    }

    return 0;
}
Beispiel #7
0
int
main(int argc, char *argv[])
{
    int r;

    if (!parse_args(argc, argv)) {
        usage(argv[0]);
        return EXIT_FAILURE;
    }

    if (sol_init() < 0) {
        SOL_CRI("Cannot initialize soletta.");
        return EXIT_FAILURE;
    }

    sol_idle_add(startup, NULL);

    r = sol_run();

    shutdown();
    sol_shutdown();

    return r;
}
Beispiel #8
0
/**
 * Starts the initialization, the tasks and then the scheduler.
 */
int main(void)
{	
	/* disable ETM at very first */
	PINSEL10 &= ~((unsigned int)(1 << 3));

	/* Initialize BMC hardware */
	global_data.bmc_resetcause = 0x00;

	/* IPMI message sequence counter */
	global_data.seq_counter = 0x00;

	/* site number used for entity instance */
	global_data.bmc_siteno = 0x00;

	/* reset sdr list */
	sdr_list.sdr_count = 0;

	/* init PLL */
	init_clock();
	
	/* init interrupts */
	init_irq();

	/* get reset cause */
	init_resetcause();
	
	/* init port pins */
	init_portpins();
	
	/* CUSTOM BOARD INIT CODE LOCATION 1 */
	custom_init_1();
	
	/* get HW and IPMB address */
	custom_get_hw_ipmb_address();

	uptime_init();

	/* init RTC */
	rtc_init();

	/* create the FreeRTOS queues */
	create_queues();

	uart_init(UART_DEBUG_CONNECTOR, 115200);

	uart_printf("Firmware started...\n");

	/* init SPI/SSP controllers */
	spi_init();

	/* init SPI FLASH */
    spi_flash_init_devices();
	spi_flash_init(&spi_flash);
	
#ifdef CFG_MMC_I2C_MASTER
	/* init BMC master I2C bus */
	master_i2c_init(MASTER_BUS_I2C);
#endif
	/* init EEPROM file system */
	//spi_eeprom_init(&spi_eeprom);

#ifdef CFG_FS
	if (fs_init(&efs, &spi_eeprom) != 0)
	{
		uart_printf("\nEEPROM not accesable!\n");
		/* reboot bmc */
		lpc_watchdog_start(CFG_BL_WATCHDOG_TIMEOUT, WD_RESET_MODE);
		while (1);
	}
#endif

	/* init leds */
	//led_init();	
	
#ifndef CFG_ONCHIP_FLASH_GLOBAL_CONF
	/* check EEPROM areas */
	//eeprom_integrity_check_areas();
#endif

	/* init CLI (and debug console) */
	cli_uart_init(115200);

	/* handle reset type warm/cold? */
	//fru_handle_reset_type();
	
#ifdef CFG_CM
	cm_fru_get_last_known_state();
#endif

#ifdef CFG_EXT_INT
	/* init external interrupts */
	external_interrupt_init();
#endif
	
#ifdef CFG_HELPER
	/* init the helper task */
	helper_init();
#endif

#ifdef CFG_BIOS_FLASH
	/* init BIOS FLASH */
	spi_flash_init(&bios_flash);

	/* init FPGA BIOS flash selection */
	bios_restore_active_flash_from_eeprom();
#endif

	/* CUSTOM BOARD INIT CODE LOCATION 2 */
	//custom_init_2();

	/* get global configuration from EEPROM */
	global_config();
	
	/* CUSTOM BOARD INIT CODE LOCATION 3 */
	//custom_init_3();

	/* parse FRU */
	fru_init(0);

#if defined (CFG_CM) || defined (CFG_MMC) || defined (CFG_IRTM) || defined(CFG_MCMC)
	/* init the IPMB-L interface(s) */
	ipmbl_init();
#endif


#ifdef CFG_LAN
	/* read and set ncsi mac address from fru */
	custom_set_ncsi_mac();
#endif

	/* create message pool for IPMI messages */
	message_pool_init();

    /* init board task */
	board_init();

	/* init the BMC task */
	bmc_init();

#ifdef CFG_PI_SERIAL_BASIC
	/* init the payload interface */
	pi_uart_b_init(CFG_PI_PORT_RATE);
#endif /* CFG_PI_SERIAL_BASIC */

#ifdef CFG_PI_SERIAL_TERMINAL
	/* init the payload interface */
	pi_uart_t_init(CFG_PI_PORT_RATE);
#endif /* CFG_PI_SERIAL_TERMINAL */

#ifdef CFG_PI_KCS
	/* initialise kcs interface */
	kcs_init();
#endif /* CFG_PI_KCS */

#ifdef CFG_ATCA
	if (global_conf.operation_mode == OPERATION_MODE_STANDALONE)
	{
		/* configure IPMB-A and IPMB-B as master only in stanalone mode */
		master_i2c_init(IPMB0A_I2C);
		master_i2c_init(IPMB0B_I2C);

		/* enable IPMB-0 pull ups and buffer */
		ipmb0_bus_ctrl(IPMB0_A, IPMB_ENABLE);
		ipmb0_bus_ctrl(IPMB0_B, IPMB_ENABLE);
	}
	else
	{
		/* init the IPMB-0 interface */
		ipmb0_init();
	}
#endif

#ifdef CFG_LAN_PLUS
	sol_init();
#endif

#ifdef CFG_LAN
	/* init ethernet hardware and Task */
	eth_start();
#endif

	/* init the SDR task */
	/* PORT_NOTE: Needs to be started AFTER BMC task because of Semaphore dependency */
	sdr_init();

	/* parse all PICMG Records in FRU data and store relevant information */
	//fru_parse_picmg();

	/* init the IPMI message hub */
	msg_hub_init();

	/* init the event task */
	event_init();


#ifdef CFG_CM
	/* init the CM task */
	init_cm();
#endif


#ifdef CFG_COOLING_MANAGER
	cool_init();
#endif
	/* do all post tests */
	//post_test();

	/* needs to be done after sdr initialization */
	//hpm_check_bl_flags();

#ifdef CFG_BIOS_FLASH
	/* collect BIOS/NVRAM version info (if payload power is off) */
	if (!(signal_read(&sig_payload_power_enable)))
	{
		bios_redundancy_get_versions();
	}
#endif


#ifdef CFG_WATCHDOG
	/* start the FW watchdog */
	lpc_watchdog_start(CFG_FW_WATCHDOG_TIMEOUT, WD_RESET_MODE);
#endif

	/* set desired debug output mode before starting scheduler */
	global_debug_uart_enabled = CFG_GLOBAL_DEBUG_UART;

	/* all tasks have been initialized, start the scheduler */
	vTaskStartScheduler();

	/* Should never reach here! */
	while (1);
}
Beispiel #9
0
/** Initialize the FreeWPC program. */
__noreturn__ void freewpc_init (void)
{
    extern __common__ void system_reset (void);

    /* Initialize the platform specifics first */
    VOIDCALL (platform_init);

    /* Reset the blanking and watchdog circuitry.
     * Eventually, the watchdog will be tickled every 1ms
     * by the IRQ; until interrupts are enabled, we will
     * have to do this periodically ourselves. */
    pinio_watchdog_reset ();

    /* Set init complete flag to false.  When everything is
     * ready, we'll change this to a 1. */
    sys_init_complete = 0;
    periodic_ok = 0;
    sys_init_pending_tasks = 0;

    /* Initialize all of the other kernel subsystems,
     * starting with the hardware-centric ones and moving on
     * to software features. */

    /* Initialize the real-time scheduler.  The periodic functions
    are scheduled at compile-time  using the 'gensched' utility. */
    VOIDCALL (tick_init);

    /* Initialize the hardware.
     * After each init call, tickle the watchdog (IRQ isn't enabled yet)
     * to prevent it from expiring and resetting the CPU.
     * We don't use a callset here because there are some ordering
     * dependencies -- some modules must be initialized before others --
     * and gencallset doesn't allow us to express those conditions.
     */
#ifdef DEBUGGER
    db_init ();
    bpt_init ();
    pinio_watchdog_reset ();
#endif
    ac_init ();
    pinio_watchdog_reset ();
    sol_init ();
    pinio_watchdog_reset ();
#ifdef CONFIG_GI
    gi_init ();
    pinio_watchdog_reset ();
#endif
    display_init ();
    pinio_watchdog_reset ();
    switch_init ();
    pinio_watchdog_reset ();
    flipper_init ();
    pinio_watchdog_reset ();
    lamp_init ();
    pinio_watchdog_reset ();
    device_init ();
    pinio_watchdog_reset ();
    free_timer_init ();
    pinio_watchdog_reset ();
    sound_init ();
    pinio_watchdog_reset ();
#if (MACHINE_PIC == 1)
    pic_init ();
    pinio_watchdog_reset ();
#endif

    /* task_init is somewhat special in that it transforms the system
     * from a single task into a multitasking one.  After this, tasks
     * can be spawned if need be.  A task is created for the current
     * thread of execution, too. */
    task_init ();
    pinio_watchdog_reset ();

#ifdef CONFIG_NATIVE
    /* Notify the simulator when the core OS is up and running. */
    sim_init ();
#endif

    /* Initialize the sound board early in a background
     * thread, since it involves polling for data back from it,
     * which may take unknown (or even infinite) time. */
    sys_init_pending_tasks++;
    task_create_gid (GID_SOUND_INIT, sound_board_init);

    /* Enable interrupts (IRQs and FIRQs).  Do this as soon as possible,
     * but not before all of the hardware modules are done. */
    enable_interrupts ();

    /* Initialize everything else.  Some of these are given explicitly
    to force a particular order, since callsets do not guarantee the
    order of invocation.  For most things the order doesn't matter. */
    deff_init ();
    leff_init ();
    test_init ();
    adj_init ();
    log_init ();
    callset_invoke (init);

    /* Check all adjustments and make sure that their checksums are valid.
    If problems are found, those adjustments will be made sane again. */
    csum_area_check_all ();

    /* Enable periodic processing. */
    periodic_ok = 1;
    task_sleep (TIME_16MS);

    /* The system is initialized from a hardware perspective.
     * Now, perform additional final initializations. */
    system_reset ();

    /* The system can run itself now, this task is done! */
    task_exit ();
}
Beispiel #10
0
/* Need to make this a function main called from a GO main wrapper */
int
ipmi_sim_main(int argc, const char *argv[])
{
    sys_data_t  sysinfo;
    misc_data_t data;
    int err, rv = 1;
    int i;
    poptContext poptCtx;
    struct timeval tv;
    console_info_t stdio_console;
    struct sigaction act;
    os_hnd_fd_id_t *conid;
    lmc_data_t *mc;
    int print_version = 0;

    poptCtx = poptGetContext(argv[0], argc, argv, poptOpts, 0);
    while ((i = poptGetNextOpt(poptCtx)) >= 0) {
	switch (i) {
	    case 'd':
		debug++;
		break;
	    case 'n':
		nostdio = 1;
		break;
	    case 'v':
		print_version = 1;
		break;
	}
    }
    poptFreeContext(poptCtx);

    printf("IPMI Simulator version %s\n", PVERSION);

    data.os_hnd = ipmi_posix_setup_os_handler();
    if (!data.os_hnd) {
	fprintf(stderr, "Unable to allocate OS handler\n");
	exit(1);
    }

    err = os_handler_alloc_waiter_factory(data.os_hnd, 0, 0,
					  &data.waiter_factory);
    if (err) {
	fprintf(stderr, "Unable to allocate waiter factory: 0x%x\n", err);
	exit(1);
    }

    err = data.os_hnd->alloc_timer(data.os_hnd, &data.timer);
    if (err) {
	fprintf(stderr, "Unable to allocate timer: 0x%x\n", err);
	exit(1);
    }

    sysinfo_init(&sysinfo);
    sysinfo.info = &data;
    sysinfo.alloc = balloc;
    sysinfo.free = bfree;
    sysinfo.get_monotonic_time = ipmi_get_monotonic_time;
    sysinfo.get_real_time = ipmi_get_real_time;
    sysinfo.alloc_timer = ipmi_alloc_timer;
    sysinfo.start_timer = ipmi_start_timer;
    sysinfo.stop_timer = ipmi_stop_timer;
    sysinfo.free_timer = ipmi_free_timer;
    sysinfo.add_io_hnd = ipmi_add_io_hnd;
    sysinfo.io_set_hnds = ipmi_io_set_hnds;
    sysinfo.io_set_enables = ipmi_io_set_enables;
    sysinfo.remove_io_hnd = ipmi_remove_io_hnd;
    sysinfo.gen_rand = sys_gen_rand;
    sysinfo.debug = debug;
    sysinfo.log = sim_log;
    sysinfo.csmi_send = smi_send;
    sysinfo.clog = sim_chan_log;
    sysinfo.calloc = ialloc;
    sysinfo.cfree = ifree;
    sysinfo.lan_channel_init = lan_channel_init;
    sysinfo.ser_channel_init = ser_channel_init;
    data.sys = &sysinfo;

    err = pipe(sigpipeh);
    if (err) {
	perror("Creating signal handling pipe");
	exit(1);
    }

    act.sa_handler = handle_sigchld;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
    
    err = sigaction(SIGCHLD, &act, NULL);
    if (err) {
	perror("setting up sigchld sigaction");
	exit(1);
    }

    err = data.os_hnd->add_fd_to_wait_for(data.os_hnd, sigpipeh[0],
					  sigchld_ready, &data,
					  NULL, &conid);
    if (err) {
	fprintf(stderr, "Unable to sigchld pipe wait: 0x%x\n", err);
	exit(1);
    }

    data.emu = ipmi_emu_alloc(&data, sleeper, &sysinfo);

    /* Set this up for console I/O, even if we don't use it. */
    stdio_console.data = &data;
    stdio_console.outfd = 1;
    stdio_console.pos = 0;
    stdio_console.echo = 1;
    stdio_console.shutdown_on_close = 1;
    stdio_console.telnet = 0;
    stdio_console.tn_pos = 0;
    if (nostdio) {
	stdio_console.out.printf = dummy_printf;
	stdio_console.out.data = &stdio_console;
    } else {
	stdio_console.out.printf = emu_printf;
	stdio_console.out.data = &stdio_console;
    }
    stdio_console.next = NULL;
    stdio_console.prev = NULL;
    data.consoles = &stdio_console;

    err = ipmi_mc_alloc_unconfigured(&sysinfo, 0x20, &mc);
    if (err) {
	if (err == ENOMEM)
	    fprintf(stderr, "Out of memory allocation BMC MC\n");
	exit(1);
    }
    sysinfo.mc = mc;
    sysinfo.chan_set = ipmi_mc_get_channelset(mc);
    sysinfo.startcmd = ipmi_mc_get_startcmdinfo(mc);
    sysinfo.cpef = ipmi_mc_get_pef(mc);
    sysinfo.cusers = ipmi_mc_get_users(mc);
    sysinfo.sol = ipmi_mc_get_sol(mc);

    if (read_config(&sysinfo, config_file, print_version))
	exit(1);

    if (print_version)
	exit(0);

    if (!sysinfo.name) {
	fprintf(stderr, "name not set in config file\n");
	exit(1);
    }

    err = persist_init("ipmi_sim", sysinfo.name, statedir);
    if (err) {
	fprintf(stderr, "Unable to initialize persistence: %s\n",
		strerror(err));
	exit(1);
    }

    read_persist_users(&sysinfo);

    err = sol_init(&sysinfo);
    if (err) {
	fprintf(stderr, "Unable to initialize SOL: %s\n",
		strerror(err));
	goto out;
    }

    err = read_sol_config(&sysinfo);
    if (err) {
	fprintf(stderr, "Unable to read SOL configs: %s\n",
		strerror(err));
	goto out;
    }

    err = load_dynamic_libs(&sysinfo, 0);
    if (err)
	goto out;

    if (!command_file) {
	FILE *tf;
	command_file = malloc(strlen(BASE_CONF_STR) + 6 + strlen(sysinfo.name));
	if (!command_file) {
	    fprintf(stderr, "Out of memory\n");
	    goto out;
	}
	strcpy(command_file, BASE_CONF_STR);
	strcat(command_file, "/");
	strcat(command_file, sysinfo.name);
	strcat(command_file, ".emu");
	tf = fopen(command_file, "r");
	if (!tf) {
	    free(command_file);
	    command_file = NULL;
	} else {
	    fclose(tf);
	}
    }

    if (command_file)
	read_command_file(&stdio_console.out, data.emu, command_file);

    if (command_string)
	ipmi_emu_cmd(&stdio_console.out, data.emu, command_string);

    if (!sysinfo.bmc_ipmb || !sysinfo.ipmb_addrs[sysinfo.bmc_ipmb]) {
	sysinfo.log(&sysinfo, SETUP_ERROR, NULL,
		    "No bmc_ipmb specified or configured.");
	goto out;
    }

    sysinfo.console_fd = -1;
    if (sysinfo.console_addr_len) {
	int nfd;
	int val;

	nfd = socket(sysinfo.console_addr.s_ipsock.s_addr.sa_family,
		     SOCK_STREAM, IPPROTO_TCP);
	if (nfd == -1) {
	    perror("Console socket open");
	    goto out;
	}
	err = bind(nfd, (struct sockaddr *) &sysinfo.console_addr,
		   sysinfo.console_addr_len);
	if (err) {
	    perror("bind to console socket");
	    goto out;
	}
	err = listen(nfd, 1);
	if (err == -1) {
	    perror("listen to console socket");
	    goto out;
	}
	val = 1;
	err = setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR,
			 (char *)&val, sizeof(val));
	if (err) {
	    perror("console setsockopt reuseaddr");
	    goto out;
	}
	sysinfo.console_fd = nfd;

	err = data.os_hnd->add_fd_to_wait_for(data.os_hnd, nfd,
					      console_bind_ready, &data,
					      NULL, &conid);
	if (err) {
	    fprintf(stderr, "Unable to add console wait: 0x%x\n", err);
	    goto out;
	}
    }

    if (!nostdio) {
	init_term();

	err = write(1, "> ", 2);
	err = data.os_hnd->add_fd_to_wait_for(data.os_hnd, 0,
					      user_data_ready, &stdio_console,
					      NULL, &stdio_console.conid);
	if (err) {
	    fprintf(stderr, "Unable to add input wait: 0x%x\n", err);
	    goto out;
	}
    }

    post_init_dynamic_libs(&sysinfo);

    act.sa_handler = shutdown_handler;
    act.sa_flags = SA_RESETHAND;
    for (i = 0; shutdown_sigs[i]; i++) {
	err = sigaction(shutdown_sigs[i], &act, NULL);
	if (err) {
	    fprintf(stderr, "Unable to register shutdown signal %d: %s\n",
		    shutdown_sigs[i], strerror(errno));
	}
    }

    tv.tv_sec = 1;
    tv.tv_usec = 0;
    err = data.os_hnd->start_timer(data.os_hnd, data.timer, &tv, tick, &data);
    if (err) {
	fprintf(stderr, "Unable to start timer: 0x%x\n", err);
	goto out;
    }

    data.os_hnd->operation_loop(data.os_hnd);
    rv = 0;
  out:
    shutdown_handler(0);
    exit(rv);
}
Beispiel #11
0
int
main(int argc, char *argv[])
{
    struct sol_coap_server *server;
    struct sol_str_slice *path;
    struct sol_network_link_addr cliaddr = { };
    struct sol_coap_packet *req;
    uint8_t observe = 0;
    int i, r;
    struct sol_network_link_addr servaddr = { .family = SOL_NETWORK_FAMILY_INET6,
                                              .port = 0 };

    uint8_t token[4] = { 0x41, 0x42, 0x43, 0x44 };

    sol_init();

    if (argc < 3) {
        printf("Usage: %s <address> <path> [path]\n", argv[0]);
        return 0;
    }

    server = sol_coap_server_new(&servaddr);
    if (!server) {
        SOL_WRN("Could not create a coap server.");
        return -1;
    }

    req = sol_coap_packet_request_new(SOL_COAP_METHOD_GET, SOL_COAP_TYPE_CON);
    if (!req) {
        SOL_WRN("Could not make a GET request to resource %s", argv[2]);
        return -1;
    }

    r = sol_coap_header_set_token(req, token, sizeof(token));
    if (r < 0) {
        SOL_WRN("Could not set coap header token.");
        return -1;
    }

    path = calloc(argc - 1, sizeof(*path));
    if (!path) {
        sol_coap_packet_unref(req);
        return -1;
    }

    for (i = 2; i < argc; i++) {
        path[i - 2] = sol_str_slice_from_str(argv[i]);
    }

    sol_coap_add_option(req, SOL_COAP_OPTION_OBSERVE, &observe, sizeof(observe));

    for (i = 0; path[i].data; i++)
        sol_coap_add_option(req, SOL_COAP_OPTION_URI_PATH, path[i].data, path[i].len);

    cliaddr.family = SOL_NETWORK_FAMILY_INET6;
    if (!sol_network_link_addr_from_str(&cliaddr, argv[1])) {
        SOL_WRN("%s is an invalid IPv6 address", argv[1]);
        free(path);
        sol_coap_packet_unref(req);
        return -1;
    }

    cliaddr.port = DEFAULT_UDP_PORT;

    /* Takes the ownership of 'req'. */
    sol_coap_send_packet_with_reply(server, req, &cliaddr, reply_cb, path);

    sol_run();

    sol_coap_server_unref(server);
    free(path);

    return 0;
}