Free (GPLv2) TCP/IP stack developed by TASS Belgium
Fork of PicoTCP by
modules/pico_icmp4.c@1:cfe8984a32b4, 2013-05-17 (annotated)
- Committer:
- tass
- Date:
- Fri May 17 12:09:59 2013 +0000
- Revision:
- 1:cfe8984a32b4
- Parent:
- libraries/picotcp/modules/pico_icmp4.c@0:d7f2341ab245
Update for smaller SOCKETQ
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
daniele | 0:d7f2341ab245 | 1 | /********************************************************************* |
daniele | 0:d7f2341ab245 | 2 | PicoTCP. Copyright (c) 2012 TASS Belgium NV. Some rights reserved. |
daniele | 0:d7f2341ab245 | 3 | See LICENSE and COPYING for usage. |
daniele | 0:d7f2341ab245 | 4 | |
daniele | 0:d7f2341ab245 | 5 | . |
daniele | 0:d7f2341ab245 | 6 | |
daniele | 0:d7f2341ab245 | 7 | Authors: Daniele Lacamera |
daniele | 0:d7f2341ab245 | 8 | *********************************************************************/ |
daniele | 0:d7f2341ab245 | 9 | |
daniele | 0:d7f2341ab245 | 10 | |
daniele | 0:d7f2341ab245 | 11 | #include "pico_icmp4.h" |
daniele | 0:d7f2341ab245 | 12 | #include "pico_config.h" |
daniele | 0:d7f2341ab245 | 13 | #include "pico_ipv4.h" |
daniele | 0:d7f2341ab245 | 14 | #include "pico_eth.h" |
daniele | 0:d7f2341ab245 | 15 | #include "pico_device.h" |
daniele | 0:d7f2341ab245 | 16 | #include "pico_stack.h" |
daniele | 0:d7f2341ab245 | 17 | #include "pico_tree.h" |
daniele | 0:d7f2341ab245 | 18 | |
daniele | 0:d7f2341ab245 | 19 | /* Queues */ |
daniele | 0:d7f2341ab245 | 20 | static struct pico_queue icmp_in = {}; |
daniele | 0:d7f2341ab245 | 21 | static struct pico_queue icmp_out = {}; |
daniele | 0:d7f2341ab245 | 22 | |
daniele | 0:d7f2341ab245 | 23 | |
daniele | 0:d7f2341ab245 | 24 | /* Functions */ |
daniele | 0:d7f2341ab245 | 25 | |
daniele | 0:d7f2341ab245 | 26 | static int pico_icmp4_checksum(struct pico_frame *f) |
daniele | 0:d7f2341ab245 | 27 | { |
daniele | 0:d7f2341ab245 | 28 | struct pico_icmp4_hdr *hdr = (struct pico_icmp4_hdr *) f->transport_hdr; |
daniele | 0:d7f2341ab245 | 29 | if (!hdr) { |
daniele | 0:d7f2341ab245 | 30 | pico_err = PICO_ERR_EINVAL; |
daniele | 0:d7f2341ab245 | 31 | return -1; |
daniele | 0:d7f2341ab245 | 32 | } |
daniele | 0:d7f2341ab245 | 33 | hdr->crc = 0; |
daniele | 0:d7f2341ab245 | 34 | hdr->crc = short_be(pico_checksum(hdr, f->transport_len)); |
daniele | 0:d7f2341ab245 | 35 | return 0; |
daniele | 0:d7f2341ab245 | 36 | } |
daniele | 0:d7f2341ab245 | 37 | |
daniele | 0:d7f2341ab245 | 38 | #ifdef PICO_SUPPORT_PING |
daniele | 0:d7f2341ab245 | 39 | static void ping_recv_reply(struct pico_frame *f); |
daniele | 0:d7f2341ab245 | 40 | #endif |
daniele | 0:d7f2341ab245 | 41 | |
daniele | 0:d7f2341ab245 | 42 | static int pico_icmp4_process_in(struct pico_protocol *self, struct pico_frame *f) |
daniele | 0:d7f2341ab245 | 43 | { |
daniele | 0:d7f2341ab245 | 44 | struct pico_icmp4_hdr *hdr = (struct pico_icmp4_hdr *) f->transport_hdr; |
daniele | 0:d7f2341ab245 | 45 | if (hdr->type == PICO_ICMP_ECHO) { |
daniele | 0:d7f2341ab245 | 46 | hdr->type = PICO_ICMP_ECHOREPLY; |
daniele | 0:d7f2341ab245 | 47 | /* Ugly, but the best way to get ICMP data size here. */ |
daniele | 0:d7f2341ab245 | 48 | f->transport_len = f->buffer_len - PICO_SIZE_IP4HDR; |
daniele | 0:d7f2341ab245 | 49 | if (f->dev->eth) |
daniele | 0:d7f2341ab245 | 50 | f->transport_len -= PICO_SIZE_ETHHDR; |
daniele | 0:d7f2341ab245 | 51 | pico_icmp4_checksum(f); |
daniele | 0:d7f2341ab245 | 52 | f->net_hdr = f->transport_hdr - PICO_SIZE_IP4HDR; |
daniele | 0:d7f2341ab245 | 53 | f->start = f->net_hdr; |
daniele | 0:d7f2341ab245 | 54 | f->len = f->buffer_len; |
daniele | 0:d7f2341ab245 | 55 | if (f->dev->eth) |
daniele | 0:d7f2341ab245 | 56 | f->len -= PICO_SIZE_ETHHDR; |
daniele | 0:d7f2341ab245 | 57 | pico_ipv4_rebound(f); |
daniele | 0:d7f2341ab245 | 58 | } else if (hdr->type == PICO_ICMP_UNREACH) { |
daniele | 0:d7f2341ab245 | 59 | f->net_hdr = f->transport_hdr + PICO_ICMPHDR_UN_SIZE; |
daniele | 0:d7f2341ab245 | 60 | pico_ipv4_unreachable(f, hdr->code); |
daniele | 0:d7f2341ab245 | 61 | } else if (hdr->type == PICO_ICMP_ECHOREPLY) { |
daniele | 0:d7f2341ab245 | 62 | #ifdef PICO_SUPPORT_PING |
daniele | 0:d7f2341ab245 | 63 | ping_recv_reply(f); |
daniele | 0:d7f2341ab245 | 64 | #endif |
daniele | 0:d7f2341ab245 | 65 | pico_frame_discard(f); |
daniele | 0:d7f2341ab245 | 66 | } else { |
daniele | 0:d7f2341ab245 | 67 | pico_frame_discard(f); |
daniele | 0:d7f2341ab245 | 68 | } |
daniele | 0:d7f2341ab245 | 69 | return 0; |
daniele | 0:d7f2341ab245 | 70 | } |
daniele | 0:d7f2341ab245 | 71 | |
daniele | 0:d7f2341ab245 | 72 | static int pico_icmp4_process_out(struct pico_protocol *self, struct pico_frame *f) |
daniele | 0:d7f2341ab245 | 73 | { |
daniele | 0:d7f2341ab245 | 74 | dbg("Called %s\n", __FUNCTION__); |
daniele | 0:d7f2341ab245 | 75 | return 0; |
daniele | 0:d7f2341ab245 | 76 | } |
daniele | 0:d7f2341ab245 | 77 | |
daniele | 0:d7f2341ab245 | 78 | /* Interface: protocol definition */ |
daniele | 0:d7f2341ab245 | 79 | struct pico_protocol pico_proto_icmp4 = { |
daniele | 0:d7f2341ab245 | 80 | .name = "icmp4", |
daniele | 0:d7f2341ab245 | 81 | .proto_number = PICO_PROTO_ICMP4, |
daniele | 0:d7f2341ab245 | 82 | .layer = PICO_LAYER_TRANSPORT, |
daniele | 0:d7f2341ab245 | 83 | .process_in = pico_icmp4_process_in, |
daniele | 0:d7f2341ab245 | 84 | .process_out = pico_icmp4_process_out, |
daniele | 0:d7f2341ab245 | 85 | .q_in = &icmp_in, |
daniele | 0:d7f2341ab245 | 86 | .q_out = &icmp_out, |
daniele | 0:d7f2341ab245 | 87 | }; |
daniele | 0:d7f2341ab245 | 88 | |
daniele | 0:d7f2341ab245 | 89 | static int pico_icmp4_notify(struct pico_frame *f, uint8_t type, uint8_t code) |
daniele | 0:d7f2341ab245 | 90 | { |
daniele | 0:d7f2341ab245 | 91 | struct pico_frame *reply; |
daniele | 0:d7f2341ab245 | 92 | struct pico_icmp4_hdr *hdr; |
daniele | 0:d7f2341ab245 | 93 | struct pico_ipv4_hdr *info; |
daniele | 0:d7f2341ab245 | 94 | if (f == NULL) { |
daniele | 0:d7f2341ab245 | 95 | pico_err = PICO_ERR_EINVAL; |
daniele | 0:d7f2341ab245 | 96 | return -1; |
daniele | 0:d7f2341ab245 | 97 | } |
daniele | 0:d7f2341ab245 | 98 | reply = pico_proto_ipv4.alloc(&pico_proto_ipv4, 8 + sizeof(struct pico_ipv4_hdr) + PICO_ICMPHDR_UN_SIZE); |
daniele | 0:d7f2341ab245 | 99 | info = (struct pico_ipv4_hdr*)(f->net_hdr); |
daniele | 0:d7f2341ab245 | 100 | hdr = (struct pico_icmp4_hdr *) reply->transport_hdr; |
daniele | 0:d7f2341ab245 | 101 | hdr->type = type; |
daniele | 0:d7f2341ab245 | 102 | hdr->code = code; |
daniele | 0:d7f2341ab245 | 103 | hdr->hun.ih_pmtu.ipm_nmtu = short_be(1500); |
daniele | 0:d7f2341ab245 | 104 | hdr->hun.ih_pmtu.ipm_void = 0; |
daniele | 0:d7f2341ab245 | 105 | reply->transport_len = 8 + sizeof(struct pico_ipv4_hdr) + PICO_ICMPHDR_UN_SIZE; |
daniele | 0:d7f2341ab245 | 106 | reply->payload = reply->transport_hdr + PICO_ICMPHDR_UN_SIZE; |
daniele | 0:d7f2341ab245 | 107 | memcpy(reply->payload, f->net_hdr, 8 + sizeof(struct pico_ipv4_hdr)); |
daniele | 0:d7f2341ab245 | 108 | pico_icmp4_checksum(reply); |
daniele | 0:d7f2341ab245 | 109 | pico_ipv4_frame_push(reply, &info->src, PICO_PROTO_ICMP4); |
daniele | 0:d7f2341ab245 | 110 | return 0; |
daniele | 0:d7f2341ab245 | 111 | } |
daniele | 0:d7f2341ab245 | 112 | |
daniele | 0:d7f2341ab245 | 113 | int pico_icmp4_port_unreachable(struct pico_frame *f) |
daniele | 0:d7f2341ab245 | 114 | { |
daniele | 0:d7f2341ab245 | 115 | /*Parameter check executed in pico_icmp4_notify*/ |
daniele | 0:d7f2341ab245 | 116 | return pico_icmp4_notify(f, PICO_ICMP_UNREACH, PICO_ICMP_UNREACH_PORT); |
daniele | 0:d7f2341ab245 | 117 | } |
daniele | 0:d7f2341ab245 | 118 | |
daniele | 0:d7f2341ab245 | 119 | int pico_icmp4_proto_unreachable(struct pico_frame *f) |
daniele | 0:d7f2341ab245 | 120 | { |
daniele | 0:d7f2341ab245 | 121 | /*Parameter check executed in pico_icmp4_notify*/ |
daniele | 0:d7f2341ab245 | 122 | return pico_icmp4_notify(f, PICO_ICMP_UNREACH, PICO_ICMP_UNREACH_PROTOCOL); |
daniele | 0:d7f2341ab245 | 123 | } |
daniele | 0:d7f2341ab245 | 124 | |
daniele | 0:d7f2341ab245 | 125 | int pico_icmp4_dest_unreachable(struct pico_frame *f) |
daniele | 0:d7f2341ab245 | 126 | { |
daniele | 0:d7f2341ab245 | 127 | /*Parameter check executed in pico_icmp4_notify*/ |
daniele | 0:d7f2341ab245 | 128 | return pico_icmp4_notify(f, PICO_ICMP_UNREACH, PICO_ICMP_UNREACH_HOST); |
daniele | 0:d7f2341ab245 | 129 | } |
daniele | 0:d7f2341ab245 | 130 | |
daniele | 0:d7f2341ab245 | 131 | int pico_icmp4_ttl_expired(struct pico_frame *f) |
daniele | 0:d7f2341ab245 | 132 | { |
daniele | 0:d7f2341ab245 | 133 | /*Parameter check executed in pico_icmp4_notify*/ |
daniele | 0:d7f2341ab245 | 134 | return pico_icmp4_notify(f, PICO_ICMP_TIME_EXCEEDED, PICO_ICMP_TIMXCEED_INTRANS); |
daniele | 0:d7f2341ab245 | 135 | } |
daniele | 0:d7f2341ab245 | 136 | |
daniele | 0:d7f2341ab245 | 137 | #ifdef PICO_SUPPORT_IPFILTER |
daniele | 0:d7f2341ab245 | 138 | int pico_icmp4_packet_filtered(struct pico_frame *f) |
daniele | 0:d7f2341ab245 | 139 | { |
daniele | 0:d7f2341ab245 | 140 | /*Parameter check executed in pico_icmp4_notify*/ |
daniele | 0:d7f2341ab245 | 141 | /*Packet Filtered: type 3, code 13 (Communication Administratively Prohibited)*/ |
daniele | 0:d7f2341ab245 | 142 | return pico_icmp4_notify(f, PICO_ICMP_UNREACH, PICO_ICMP_UNREACH_FILTER_PROHIB); |
daniele | 0:d7f2341ab245 | 143 | } |
daniele | 0:d7f2341ab245 | 144 | #endif |
daniele | 0:d7f2341ab245 | 145 | |
daniele | 0:d7f2341ab245 | 146 | /***********************/ |
daniele | 0:d7f2341ab245 | 147 | /* Ping implementation */ |
daniele | 0:d7f2341ab245 | 148 | /***********************/ |
daniele | 0:d7f2341ab245 | 149 | /***********************/ |
daniele | 0:d7f2341ab245 | 150 | /***********************/ |
daniele | 0:d7f2341ab245 | 151 | /***********************/ |
daniele | 0:d7f2341ab245 | 152 | |
daniele | 0:d7f2341ab245 | 153 | |
daniele | 0:d7f2341ab245 | 154 | #ifdef PICO_SUPPORT_PING |
daniele | 0:d7f2341ab245 | 155 | |
daniele | 0:d7f2341ab245 | 156 | |
daniele | 0:d7f2341ab245 | 157 | struct pico_icmp4_ping_cookie |
daniele | 0:d7f2341ab245 | 158 | { |
daniele | 0:d7f2341ab245 | 159 | struct pico_ip4 dst; |
daniele | 0:d7f2341ab245 | 160 | uint16_t err; |
daniele | 0:d7f2341ab245 | 161 | uint16_t id; |
daniele | 0:d7f2341ab245 | 162 | uint16_t seq; |
daniele | 0:d7f2341ab245 | 163 | uint16_t size; |
daniele | 0:d7f2341ab245 | 164 | int count; |
daniele | 0:d7f2341ab245 | 165 | unsigned long timestamp; |
daniele | 0:d7f2341ab245 | 166 | int interval; |
daniele | 0:d7f2341ab245 | 167 | int timeout; |
daniele | 0:d7f2341ab245 | 168 | void (*cb)(struct pico_icmp4_stats*); |
daniele | 0:d7f2341ab245 | 169 | |
daniele | 0:d7f2341ab245 | 170 | }; |
daniele | 0:d7f2341ab245 | 171 | |
daniele | 0:d7f2341ab245 | 172 | static int cookie_compare(void *ka, void *kb) |
daniele | 0:d7f2341ab245 | 173 | { |
daniele | 0:d7f2341ab245 | 174 | struct pico_icmp4_ping_cookie *a = ka, *b = kb; |
daniele | 0:d7f2341ab245 | 175 | if (a->id < b->id) |
daniele | 0:d7f2341ab245 | 176 | return -1; |
daniele | 0:d7f2341ab245 | 177 | if (a->id > b->id) |
daniele | 0:d7f2341ab245 | 178 | return 1; |
daniele | 0:d7f2341ab245 | 179 | return (a->seq - b->seq); |
daniele | 0:d7f2341ab245 | 180 | } |
daniele | 0:d7f2341ab245 | 181 | |
daniele | 0:d7f2341ab245 | 182 | PICO_TREE_DECLARE(Pings,cookie_compare); |
daniele | 0:d7f2341ab245 | 183 | |
daniele | 0:d7f2341ab245 | 184 | static int pico_icmp4_send_echo(struct pico_icmp4_ping_cookie *cookie) |
daniele | 0:d7f2341ab245 | 185 | { |
daniele | 0:d7f2341ab245 | 186 | struct pico_frame *echo = pico_proto_ipv4.alloc(&pico_proto_ipv4, PICO_ICMPHDR_UN_SIZE + cookie->size); |
daniele | 0:d7f2341ab245 | 187 | struct pico_icmp4_hdr *hdr; |
daniele | 0:d7f2341ab245 | 188 | |
daniele | 0:d7f2341ab245 | 189 | hdr = (struct pico_icmp4_hdr *) echo->transport_hdr; |
daniele | 0:d7f2341ab245 | 190 | |
daniele | 0:d7f2341ab245 | 191 | hdr->type = PICO_ICMP_ECHO; |
daniele | 0:d7f2341ab245 | 192 | hdr->code = 0; |
daniele | 0:d7f2341ab245 | 193 | hdr->hun.ih_idseq.idseq_id = short_be(cookie->id); |
daniele | 0:d7f2341ab245 | 194 | hdr->hun.ih_idseq.idseq_seq = short_be(cookie->seq); |
daniele | 0:d7f2341ab245 | 195 | echo->transport_len = PICO_ICMPHDR_UN_SIZE + cookie->size; |
daniele | 0:d7f2341ab245 | 196 | echo->payload = echo->transport_hdr + PICO_ICMPHDR_UN_SIZE; |
daniele | 0:d7f2341ab245 | 197 | echo->payload_len = cookie->size; |
daniele | 0:d7f2341ab245 | 198 | /* XXX: Fill payload */ |
daniele | 0:d7f2341ab245 | 199 | pico_icmp4_checksum(echo); |
daniele | 0:d7f2341ab245 | 200 | pico_ipv4_frame_push(echo, &cookie->dst, PICO_PROTO_ICMP4); |
daniele | 0:d7f2341ab245 | 201 | return 0; |
daniele | 0:d7f2341ab245 | 202 | } |
daniele | 0:d7f2341ab245 | 203 | |
daniele | 0:d7f2341ab245 | 204 | |
daniele | 0:d7f2341ab245 | 205 | static void ping_timeout(unsigned long now, void *arg) |
daniele | 0:d7f2341ab245 | 206 | { |
daniele | 0:d7f2341ab245 | 207 | struct pico_icmp4_ping_cookie *cookie = (struct pico_icmp4_ping_cookie *)arg; |
daniele | 0:d7f2341ab245 | 208 | if(pico_tree_findKey(&Pings,cookie)){ |
daniele | 0:d7f2341ab245 | 209 | if (cookie->err == PICO_PING_ERR_PENDING) { |
daniele | 0:d7f2341ab245 | 210 | struct pico_icmp4_stats stats; |
daniele | 0:d7f2341ab245 | 211 | stats.dst = cookie->dst; |
daniele | 0:d7f2341ab245 | 212 | stats.seq = cookie->seq; |
daniele | 0:d7f2341ab245 | 213 | stats.time = 0; |
daniele | 0:d7f2341ab245 | 214 | stats.size = cookie->size; |
daniele | 0:d7f2341ab245 | 215 | stats.err = PICO_PING_ERR_TIMEOUT; |
daniele | 0:d7f2341ab245 | 216 | dbg(" ---- Ping timeout!!!\n"); |
daniele | 0:d7f2341ab245 | 217 | cookie->cb(&stats); |
daniele | 0:d7f2341ab245 | 218 | } |
daniele | 0:d7f2341ab245 | 219 | |
daniele | 0:d7f2341ab245 | 220 | pico_tree_delete(&Pings,cookie); |
daniele | 0:d7f2341ab245 | 221 | pico_free(cookie); |
daniele | 0:d7f2341ab245 | 222 | } |
daniele | 0:d7f2341ab245 | 223 | } |
daniele | 0:d7f2341ab245 | 224 | |
daniele | 0:d7f2341ab245 | 225 | static void next_ping(unsigned long now, void *arg); |
daniele | 0:d7f2341ab245 | 226 | static inline void send_ping(struct pico_icmp4_ping_cookie *cookie) |
daniele | 0:d7f2341ab245 | 227 | { |
daniele | 0:d7f2341ab245 | 228 | pico_icmp4_send_echo(cookie); |
daniele | 0:d7f2341ab245 | 229 | cookie->timestamp = pico_tick; |
daniele | 0:d7f2341ab245 | 230 | pico_timer_add(cookie->timeout, ping_timeout, cookie); |
daniele | 0:d7f2341ab245 | 231 | pico_timer_add(cookie->interval, next_ping, cookie); |
daniele | 0:d7f2341ab245 | 232 | } |
daniele | 0:d7f2341ab245 | 233 | |
daniele | 0:d7f2341ab245 | 234 | static void next_ping(unsigned long now, void *arg) |
daniele | 0:d7f2341ab245 | 235 | { |
daniele | 0:d7f2341ab245 | 236 | struct pico_icmp4_ping_cookie *newcookie, *cookie = (struct pico_icmp4_ping_cookie *)arg; |
daniele | 0:d7f2341ab245 | 237 | |
daniele | 0:d7f2341ab245 | 238 | if(pico_tree_findKey(&Pings,cookie)){ |
daniele | 0:d7f2341ab245 | 239 | if (cookie->seq < cookie->count) { |
daniele | 0:d7f2341ab245 | 240 | newcookie = pico_zalloc(sizeof(struct pico_icmp4_ping_cookie)); |
daniele | 0:d7f2341ab245 | 241 | if (!newcookie) |
daniele | 0:d7f2341ab245 | 242 | return; |
daniele | 0:d7f2341ab245 | 243 | memcpy(newcookie, cookie, sizeof(struct pico_icmp4_ping_cookie)); |
daniele | 0:d7f2341ab245 | 244 | newcookie->seq++; |
daniele | 0:d7f2341ab245 | 245 | |
daniele | 0:d7f2341ab245 | 246 | pico_tree_insert(&Pings,newcookie); |
daniele | 0:d7f2341ab245 | 247 | send_ping(newcookie); |
daniele | 0:d7f2341ab245 | 248 | } |
daniele | 0:d7f2341ab245 | 249 | } |
daniele | 0:d7f2341ab245 | 250 | } |
daniele | 0:d7f2341ab245 | 251 | |
daniele | 0:d7f2341ab245 | 252 | |
daniele | 0:d7f2341ab245 | 253 | static void ping_recv_reply(struct pico_frame *f) |
daniele | 0:d7f2341ab245 | 254 | { |
daniele | 0:d7f2341ab245 | 255 | struct pico_icmp4_ping_cookie test, *cookie; |
daniele | 0:d7f2341ab245 | 256 | struct pico_icmp4_hdr *hdr = (struct pico_icmp4_hdr *) f->transport_hdr; |
daniele | 0:d7f2341ab245 | 257 | test.id = short_be(hdr->hun.ih_idseq.idseq_id ); |
daniele | 0:d7f2341ab245 | 258 | test.seq = short_be(hdr->hun.ih_idseq.idseq_seq); |
daniele | 0:d7f2341ab245 | 259 | |
daniele | 0:d7f2341ab245 | 260 | cookie = pico_tree_findKey(&Pings, &test); |
daniele | 0:d7f2341ab245 | 261 | if (cookie) { |
daniele | 0:d7f2341ab245 | 262 | struct pico_icmp4_stats stats; |
daniele | 0:d7f2341ab245 | 263 | cookie->err = PICO_PING_ERR_REPLIED; |
daniele | 0:d7f2341ab245 | 264 | stats.dst = cookie->dst; |
daniele | 0:d7f2341ab245 | 265 | stats.seq = cookie->seq; |
daniele | 0:d7f2341ab245 | 266 | stats.size = cookie->size; |
daniele | 0:d7f2341ab245 | 267 | stats.time = pico_tick - cookie->timestamp; |
daniele | 0:d7f2341ab245 | 268 | stats.err = cookie->err; |
daniele | 0:d7f2341ab245 | 269 | stats.ttl = ((struct pico_ipv4_hdr *)f->net_hdr)->ttl; |
daniele | 0:d7f2341ab245 | 270 | if(cookie->cb != NULL) |
daniele | 0:d7f2341ab245 | 271 | cookie->cb(&stats); |
daniele | 0:d7f2341ab245 | 272 | /* XXX cb */ |
daniele | 0:d7f2341ab245 | 273 | } else { |
daniele | 0:d7f2341ab245 | 274 | dbg("Reply for seq=%d, not found.\n", test.seq); |
daniele | 0:d7f2341ab245 | 275 | } |
daniele | 0:d7f2341ab245 | 276 | } |
daniele | 0:d7f2341ab245 | 277 | |
daniele | 0:d7f2341ab245 | 278 | int pico_icmp4_ping(char *dst, int count, int interval, int timeout, int size, void (*cb)(struct pico_icmp4_stats *)) |
daniele | 0:d7f2341ab245 | 279 | { |
daniele | 0:d7f2341ab245 | 280 | static uint16_t next_id = 0x91c0; |
daniele | 0:d7f2341ab245 | 281 | struct pico_icmp4_ping_cookie *cookie; |
daniele | 0:d7f2341ab245 | 282 | |
daniele | 0:d7f2341ab245 | 283 | if((dst == NULL) || (interval == 0) || (timeout == 0) || (count == 0)){ |
daniele | 0:d7f2341ab245 | 284 | pico_err = PICO_ERR_EINVAL; |
daniele | 0:d7f2341ab245 | 285 | return -1; |
daniele | 0:d7f2341ab245 | 286 | } |
daniele | 0:d7f2341ab245 | 287 | |
daniele | 0:d7f2341ab245 | 288 | cookie = pico_zalloc(sizeof(struct pico_icmp4_ping_cookie)); |
daniele | 0:d7f2341ab245 | 289 | if (!cookie) { |
daniele | 0:d7f2341ab245 | 290 | pico_err = PICO_ERR_ENOMEM; |
daniele | 0:d7f2341ab245 | 291 | return -1; |
daniele | 0:d7f2341ab245 | 292 | } |
daniele | 0:d7f2341ab245 | 293 | |
daniele | 0:d7f2341ab245 | 294 | if (pico_string_to_ipv4(dst, &cookie->dst.addr) < 0) { |
daniele | 0:d7f2341ab245 | 295 | pico_err = PICO_ERR_EINVAL; |
daniele | 0:d7f2341ab245 | 296 | pico_free(cookie); |
daniele | 0:d7f2341ab245 | 297 | return -1; |
daniele | 0:d7f2341ab245 | 298 | } |
daniele | 0:d7f2341ab245 | 299 | cookie->seq = 1; |
daniele | 0:d7f2341ab245 | 300 | cookie->id = next_id++; |
daniele | 0:d7f2341ab245 | 301 | cookie->err = PICO_PING_ERR_PENDING; |
daniele | 0:d7f2341ab245 | 302 | cookie->size = size; |
daniele | 0:d7f2341ab245 | 303 | cookie->interval = interval; |
daniele | 0:d7f2341ab245 | 304 | cookie->timeout = timeout; |
daniele | 0:d7f2341ab245 | 305 | cookie->cb = cb; |
daniele | 0:d7f2341ab245 | 306 | cookie->count = count; |
daniele | 0:d7f2341ab245 | 307 | |
daniele | 0:d7f2341ab245 | 308 | pico_tree_insert(&Pings,cookie); |
daniele | 0:d7f2341ab245 | 309 | send_ping(cookie); |
daniele | 0:d7f2341ab245 | 310 | |
daniele | 0:d7f2341ab245 | 311 | return 0; |
daniele | 0:d7f2341ab245 | 312 | |
daniele | 0:d7f2341ab245 | 313 | } |
daniele | 0:d7f2341ab245 | 314 | |
daniele | 0:d7f2341ab245 | 315 | #endif |