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