1#include "utils.h"
2#include <pico_ipv4.h>
3#include <pico_dhcp_client.h>
4#include <pico_socket.h>
5#include <pico_icmp4.h>
6#include <pico_device.h>
7/*** START DHCP Client ***/
8#ifdef PICO_SUPPORT_DHCPC
9
10/* This must stay global, its lifetime is the same as the dhcp negotiation */
11uint32_t dhcpclient_xid;
12
13
14static uint8_t dhcpclient_devices = 0;
15
16void ping_callback_dhcpclient(struct pico_icmp4_stats *s)
17{
18    char host[30] = { };
19
20    pico_ipv4_to_string(host, s->dst.addr);
21    if (s->err == 0) {
22        dbg("DHCP client: %lu bytes from %s: icmp_req=%lu ttl=64 time=%lu ms\n",
23            s->size, host, s->seq, (long unsigned int)s->time);
24        if (s->seq >= 3) {
25            dbg("DHCP client: TEST SUCCESS!\n");
26            if (--dhcpclient_devices <= 0)
27                exit(0);
28        }
29    } else {
30        dbg("DHCP client: ping %lu to %s error %d\n", s->seq, host, s->err);
31        dbg("DHCP client: TEST FAILED!\n");
32        exit(1);
33    }
34}
35
36void callback_dhcpclient(void *arg, int code)
37{
38    struct pico_ip4 address = ZERO_IP4, gateway = ZERO_IP4;
39    char s_address[16] = { }, s_gateway[16] = { };
40
41    printf("DHCP client: callback happened with code %d!\n", code);
42    if (code == PICO_DHCP_SUCCESS) {
43        address = pico_dhcp_get_address(arg);
44        gateway = pico_dhcp_get_gateway(arg);
45        pico_ipv4_to_string(s_address, address.addr);
46        pico_ipv4_to_string(s_gateway, gateway.addr);
47        printf("DHCP client: got IP %s assigned with cli %p\n", s_address, arg);
48#ifdef PICO_SUPPORT_PING
49        pico_icmp4_ping(s_gateway, 3, 1000, 5000, 32, ping_callback_dhcpclient);
50        /* optional test to check routing when links get added and deleted */
51        /* do {
52           char *new_arg = NULL, *p = NULL;
53           new_arg = calloc(1, strlen(s_address) + strlen(":224.7.7.7:6667:6667") + 1);
54           p = strcat(new_arg, s_address);
55           p = strcat(p + strlen(s_address), ":224.7.7.7:6667:6667");
56           app_mcastsend(new_arg);
57           } while (0);
58         */
59#endif
60    }
61}
62
63void app_dhcp_client(char *arg)
64{
65    char *sdev = NULL;
66    char *nxt = arg;
67    struct pico_device *dev = NULL;
68
69    if (!nxt)
70        goto out;
71
72    while (nxt) {
73        if (nxt) {
74            nxt = cpy_arg(&sdev, nxt);
75            if(!sdev) {
76                goto out;
77            }
78        }
79
80        dev = pico_get_device(sdev);
81        if(dev == NULL) {
82            if (sdev)
83                free(sdev);
84
85            printf("%s: error getting device %s: %s\n", __FUNCTION__, dev->name, strerror(pico_err));
86            exit(255);
87        }
88
89        printf("Starting negotiation\n");
90
91        if (pico_dhcp_initiate_negotiation(dev, &callback_dhcpclient, &dhcpclient_xid) < 0) {
92            printf("%s: error initiating negotiation: %s\n", __FUNCTION__, strerror(pico_err));
93            if (sdev)
94                free(sdev);
95
96            exit(255);
97        }
98
99        if (sdev)
100            free(sdev);
101
102        dhcpclient_devices++;
103    }
104    return;
105
106out:
107    fprintf(stderr, "dhcpclient expects the following format: dhcpclient:dev_name:[dev_name]\n");
108    if (sdev)
109        free(sdev);
110
111    exit(255);
112}
113#endif
114/*** END DHCP Client ***/
115