Free (GPLv2) TCP/IP stack developed by TASS Belgium
Fork of PicoTCP by
stack/pico_arp.c@1:cfe8984a32b4, 2013-05-17 (annotated)
- Committer:
- tass
- Date:
- Fri May 17 12:09:59 2013 +0000
- Revision:
- 1:cfe8984a32b4
- Parent:
- libraries/picotcp/stack/pico_arp.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_config.h" |
daniele | 0:d7f2341ab245 | 12 | #include "pico_arp.h" |
daniele | 0:d7f2341ab245 | 13 | #include "pico_tree.h" |
daniele | 0:d7f2341ab245 | 14 | #include "pico_ipv4.h" |
daniele | 0:d7f2341ab245 | 15 | #include "pico_device.h" |
daniele | 0:d7f2341ab245 | 16 | #include "pico_stack.h" |
daniele | 0:d7f2341ab245 | 17 | |
daniele | 0:d7f2341ab245 | 18 | const uint8_t PICO_ETHADDR_ALL[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; |
daniele | 0:d7f2341ab245 | 19 | #define PICO_ARP_TIMEOUT 600000 |
daniele | 0:d7f2341ab245 | 20 | #define PICO_ARP_RETRY 300 |
daniele | 0:d7f2341ab245 | 21 | |
daniele | 0:d7f2341ab245 | 22 | #ifdef DEBUG_ARP |
daniele | 0:d7f2341ab245 | 23 | #define arp_dbg dbg |
daniele | 0:d7f2341ab245 | 24 | #else |
daniele | 0:d7f2341ab245 | 25 | #define arp_dbg(...) do{}while(0) |
daniele | 0:d7f2341ab245 | 26 | #endif |
daniele | 0:d7f2341ab245 | 27 | |
daniele | 0:d7f2341ab245 | 28 | static struct pico_queue pending; |
daniele | 0:d7f2341ab245 | 29 | static int pending_timer_on = 0; |
daniele | 0:d7f2341ab245 | 30 | |
daniele | 0:d7f2341ab245 | 31 | void check_pending(unsigned long now, void *_unused) |
daniele | 0:d7f2341ab245 | 32 | { |
daniele | 0:d7f2341ab245 | 33 | struct pico_frame *f = pico_dequeue(&pending); |
daniele | 0:d7f2341ab245 | 34 | if (!f) { |
daniele | 0:d7f2341ab245 | 35 | pending_timer_on = 0; |
daniele | 0:d7f2341ab245 | 36 | return; |
daniele | 0:d7f2341ab245 | 37 | } |
daniele | 0:d7f2341ab245 | 38 | if(pico_ethernet_send(f) > 0) |
daniele | 0:d7f2341ab245 | 39 | pico_frame_discard(f); |
daniele | 0:d7f2341ab245 | 40 | pico_timer_add(PICO_ARP_RETRY, &check_pending, NULL); |
daniele | 0:d7f2341ab245 | 41 | } |
daniele | 0:d7f2341ab245 | 42 | |
daniele | 0:d7f2341ab245 | 43 | |
daniele | 0:d7f2341ab245 | 44 | struct |
daniele | 0:d7f2341ab245 | 45 | __attribute__ ((__packed__)) |
daniele | 0:d7f2341ab245 | 46 | pico_arp_hdr |
daniele | 0:d7f2341ab245 | 47 | { |
daniele | 0:d7f2341ab245 | 48 | uint16_t htype; |
daniele | 0:d7f2341ab245 | 49 | uint16_t ptype; |
daniele | 0:d7f2341ab245 | 50 | uint8_t hsize; |
daniele | 0:d7f2341ab245 | 51 | uint8_t psize; |
daniele | 0:d7f2341ab245 | 52 | uint16_t opcode; |
daniele | 0:d7f2341ab245 | 53 | uint8_t s_mac[PICO_SIZE_ETH]; |
daniele | 0:d7f2341ab245 | 54 | struct pico_ip4 src; |
daniele | 0:d7f2341ab245 | 55 | uint8_t d_mac[PICO_SIZE_ETH]; |
daniele | 0:d7f2341ab245 | 56 | struct pico_ip4 dst; |
daniele | 0:d7f2341ab245 | 57 | }; |
daniele | 0:d7f2341ab245 | 58 | |
daniele | 0:d7f2341ab245 | 59 | |
daniele | 0:d7f2341ab245 | 60 | #define PICO_SIZE_ARPHDR ((sizeof(struct pico_arp_hdr))) |
daniele | 0:d7f2341ab245 | 61 | |
daniele | 0:d7f2341ab245 | 62 | /* Arp Entries for the tables. */ |
daniele | 0:d7f2341ab245 | 63 | struct pico_arp { |
daniele | 0:d7f2341ab245 | 64 | /* CAREFUL MAN! ARP entry MUST begin with a pico_eth structure, |
daniele | 0:d7f2341ab245 | 65 | * due to in-place casting!!! */ |
daniele | 0:d7f2341ab245 | 66 | struct pico_eth eth; |
daniele | 0:d7f2341ab245 | 67 | struct pico_ip4 ipv4; |
daniele | 0:d7f2341ab245 | 68 | int arp_status; |
daniele | 0:d7f2341ab245 | 69 | uint32_t timestamp; |
daniele | 0:d7f2341ab245 | 70 | struct pico_device *dev; |
daniele | 0:d7f2341ab245 | 71 | }; |
daniele | 0:d7f2341ab245 | 72 | |
daniele | 0:d7f2341ab245 | 73 | |
daniele | 0:d7f2341ab245 | 74 | |
daniele | 0:d7f2341ab245 | 75 | /*****************/ |
daniele | 0:d7f2341ab245 | 76 | /** ARP TREE **/ |
daniele | 0:d7f2341ab245 | 77 | /*****************/ |
daniele | 0:d7f2341ab245 | 78 | |
daniele | 0:d7f2341ab245 | 79 | /* Routing destination */ |
daniele | 0:d7f2341ab245 | 80 | |
daniele | 0:d7f2341ab245 | 81 | static int arp_compare(void * ka, void * kb) |
daniele | 0:d7f2341ab245 | 82 | { |
daniele | 0:d7f2341ab245 | 83 | struct pico_arp *a = ka, *b = kb; |
daniele | 0:d7f2341ab245 | 84 | if (a->ipv4.addr < b->ipv4.addr) |
daniele | 0:d7f2341ab245 | 85 | return -1; |
daniele | 0:d7f2341ab245 | 86 | else if (a->ipv4.addr > b->ipv4.addr) |
daniele | 0:d7f2341ab245 | 87 | return 1; |
daniele | 0:d7f2341ab245 | 88 | return 0; |
daniele | 0:d7f2341ab245 | 89 | } |
daniele | 0:d7f2341ab245 | 90 | |
daniele | 0:d7f2341ab245 | 91 | PICO_TREE_DECLARE(arp_tree, arp_compare); |
daniele | 0:d7f2341ab245 | 92 | |
daniele | 0:d7f2341ab245 | 93 | /*********************/ |
daniele | 0:d7f2341ab245 | 94 | /** END ARP TREE **/ |
daniele | 0:d7f2341ab245 | 95 | /*********************/ |
daniele | 0:d7f2341ab245 | 96 | |
daniele | 0:d7f2341ab245 | 97 | struct pico_eth *pico_arp_lookup(struct pico_ip4 *dst) |
daniele | 0:d7f2341ab245 | 98 | { |
daniele | 0:d7f2341ab245 | 99 | struct pico_arp search, *found; |
daniele | 0:d7f2341ab245 | 100 | search.ipv4.addr = dst->addr; |
daniele | 0:d7f2341ab245 | 101 | found = pico_tree_findKey(&arp_tree,&search); |
daniele | 0:d7f2341ab245 | 102 | if (found && (found->arp_status != PICO_ARP_STATUS_STALE)) |
daniele | 0:d7f2341ab245 | 103 | return &found->eth; |
daniele | 0:d7f2341ab245 | 104 | return NULL; |
daniele | 0:d7f2341ab245 | 105 | } |
daniele | 0:d7f2341ab245 | 106 | |
daniele | 0:d7f2341ab245 | 107 | struct pico_ip4 *pico_arp_reverse_lookup(struct pico_eth *dst) |
daniele | 0:d7f2341ab245 | 108 | { |
daniele | 0:d7f2341ab245 | 109 | struct pico_arp* search; |
daniele | 0:d7f2341ab245 | 110 | struct pico_tree_node * index; |
daniele | 0:d7f2341ab245 | 111 | pico_tree_foreach(index,&arp_tree){ |
daniele | 0:d7f2341ab245 | 112 | search = index->keyValue; |
daniele | 0:d7f2341ab245 | 113 | if(memcmp(&(search->eth.addr), &dst->addr, 6) == 0) |
daniele | 0:d7f2341ab245 | 114 | return &search->ipv4; |
daniele | 0:d7f2341ab245 | 115 | } |
daniele | 0:d7f2341ab245 | 116 | return NULL; |
daniele | 0:d7f2341ab245 | 117 | } |
daniele | 0:d7f2341ab245 | 118 | |
daniele | 0:d7f2341ab245 | 119 | struct pico_eth *pico_arp_get(struct pico_frame *f) { |
daniele | 0:d7f2341ab245 | 120 | struct pico_eth *a4; |
daniele | 0:d7f2341ab245 | 121 | struct pico_ip4 gateway; |
daniele | 0:d7f2341ab245 | 122 | struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr; |
daniele | 0:d7f2341ab245 | 123 | struct pico_ipv4_link *l; |
daniele | 0:d7f2341ab245 | 124 | |
daniele | 0:d7f2341ab245 | 125 | l = pico_ipv4_link_get(&hdr->dst); |
daniele | 0:d7f2341ab245 | 126 | if(l){ |
daniele | 0:d7f2341ab245 | 127 | //address belongs to ourself |
daniele | 0:d7f2341ab245 | 128 | return &l->dev->eth->mac; |
daniele | 0:d7f2341ab245 | 129 | } |
daniele | 0:d7f2341ab245 | 130 | |
daniele | 0:d7f2341ab245 | 131 | gateway = pico_ipv4_route_get_gateway(&hdr->dst); |
daniele | 0:d7f2341ab245 | 132 | /* check if dst is local (gateway = 0), or if to use gateway */ |
daniele | 0:d7f2341ab245 | 133 | if (gateway.addr != 0) |
daniele | 0:d7f2341ab245 | 134 | a4 = pico_arp_lookup(&gateway); /* check if gateway ip mac in cache */ |
daniele | 0:d7f2341ab245 | 135 | else |
daniele | 0:d7f2341ab245 | 136 | a4 = pico_arp_lookup(&hdr->dst); /* check if local ip mac in cache */ |
daniele | 0:d7f2341ab245 | 137 | if (!a4) { |
daniele | 0:d7f2341ab245 | 138 | if (++f->failure_count < 4) { |
daniele | 0:d7f2341ab245 | 139 | dbg ("================= ARP REQUIRED: %d =============\n\n", f->failure_count); |
daniele | 0:d7f2341ab245 | 140 | /* check if dst is local (gateway = 0), or if to use gateway */ |
daniele | 0:d7f2341ab245 | 141 | if (gateway.addr != 0) |
daniele | 0:d7f2341ab245 | 142 | pico_arp_query(f->dev, &gateway); /* arp to gateway */ |
daniele | 0:d7f2341ab245 | 143 | else |
daniele | 0:d7f2341ab245 | 144 | pico_arp_query(f->dev, &hdr->dst); /* arp to dst */ |
daniele | 0:d7f2341ab245 | 145 | |
daniele | 0:d7f2341ab245 | 146 | pico_enqueue(&pending, f); |
daniele | 0:d7f2341ab245 | 147 | if (!pending_timer_on) { |
daniele | 0:d7f2341ab245 | 148 | pending_timer_on++; |
daniele | 0:d7f2341ab245 | 149 | pico_timer_add(PICO_ARP_RETRY, &check_pending, NULL); |
daniele | 0:d7f2341ab245 | 150 | } |
daniele | 0:d7f2341ab245 | 151 | } else { |
daniele | 0:d7f2341ab245 | 152 | dbg("ARP: Destination Unreachable\n"); |
daniele | 0:d7f2341ab245 | 153 | pico_notify_dest_unreachable(f); |
daniele | 0:d7f2341ab245 | 154 | pico_frame_discard(f); |
daniele | 0:d7f2341ab245 | 155 | } |
daniele | 0:d7f2341ab245 | 156 | } |
daniele | 0:d7f2341ab245 | 157 | return a4; |
daniele | 0:d7f2341ab245 | 158 | } |
daniele | 0:d7f2341ab245 | 159 | |
daniele | 0:d7f2341ab245 | 160 | #ifdef DEBUG_ARP |
daniele | 0:d7f2341ab245 | 161 | void dbg_arp(void) |
daniele | 0:d7f2341ab245 | 162 | { |
daniele | 0:d7f2341ab245 | 163 | struct pico_arp *a; |
daniele | 0:d7f2341ab245 | 164 | struct pico_tree_node * index; |
daniele | 0:d7f2341ab245 | 165 | |
daniele | 0:d7f2341ab245 | 166 | pico_tree_foreach(index,&arp_tree) { |
daniele | 0:d7f2341ab245 | 167 | a = index->keyValue; |
daniele | 0:d7f2341ab245 | 168 | arp_dbg("ARP to %08x, mac: %02x:%02x:%02x:%02x:%02x:%02x\n", a->ipv4.addr,a->eth.addr[0],a->eth.addr[1],a->eth.addr[2],a->eth.addr[3],a->eth.addr[4],a->eth.addr[5] ); |
daniele | 0:d7f2341ab245 | 169 | } |
daniele | 0:d7f2341ab245 | 170 | } |
daniele | 0:d7f2341ab245 | 171 | #endif |
daniele | 0:d7f2341ab245 | 172 | |
daniele | 0:d7f2341ab245 | 173 | void arp_expire(unsigned long now, void *_stale) |
daniele | 0:d7f2341ab245 | 174 | { |
daniele | 0:d7f2341ab245 | 175 | struct pico_arp *stale = (struct pico_arp *) _stale; |
daniele | 0:d7f2341ab245 | 176 | stale->arp_status = PICO_ARP_STATUS_STALE; |
daniele | 0:d7f2341ab245 | 177 | arp_dbg("ARP: Setting arp_status to STALE\n"); |
daniele | 0:d7f2341ab245 | 178 | pico_arp_query(stale->dev, &stale->ipv4); |
daniele | 0:d7f2341ab245 | 179 | |
daniele | 0:d7f2341ab245 | 180 | } |
daniele | 0:d7f2341ab245 | 181 | |
daniele | 0:d7f2341ab245 | 182 | void pico_arp_add_entry(struct pico_arp *entry) |
daniele | 0:d7f2341ab245 | 183 | { |
daniele | 0:d7f2341ab245 | 184 | entry->arp_status = PICO_ARP_STATUS_REACHABLE; |
daniele | 0:d7f2341ab245 | 185 | entry->timestamp = PICO_TIME(); |
daniele | 0:d7f2341ab245 | 186 | |
daniele | 0:d7f2341ab245 | 187 | pico_tree_insert(&arp_tree,entry); |
daniele | 0:d7f2341ab245 | 188 | arp_dbg("ARP ## reachable.\n"); |
daniele | 0:d7f2341ab245 | 189 | pico_timer_add(PICO_ARP_TIMEOUT, arp_expire, entry); |
daniele | 0:d7f2341ab245 | 190 | } |
daniele | 0:d7f2341ab245 | 191 | |
daniele | 0:d7f2341ab245 | 192 | int pico_arp_create_entry(uint8_t* hwaddr, struct pico_ip4 ipv4, struct pico_device* dev) |
daniele | 0:d7f2341ab245 | 193 | { |
daniele | 0:d7f2341ab245 | 194 | struct pico_arp* arp = pico_zalloc(sizeof(struct pico_arp)); |
daniele | 0:d7f2341ab245 | 195 | if(!arp){ |
daniele | 0:d7f2341ab245 | 196 | pico_err = PICO_ERR_ENOMEM; |
daniele | 0:d7f2341ab245 | 197 | return -1; |
daniele | 0:d7f2341ab245 | 198 | } |
daniele | 0:d7f2341ab245 | 199 | memcpy(arp->eth.addr, hwaddr, 6); |
daniele | 0:d7f2341ab245 | 200 | arp->ipv4.addr = ipv4.addr; |
daniele | 0:d7f2341ab245 | 201 | arp->dev = dev; |
daniele | 0:d7f2341ab245 | 202 | |
daniele | 0:d7f2341ab245 | 203 | pico_arp_add_entry(arp); |
daniele | 0:d7f2341ab245 | 204 | |
daniele | 0:d7f2341ab245 | 205 | return 0; |
daniele | 0:d7f2341ab245 | 206 | } |
daniele | 0:d7f2341ab245 | 207 | |
daniele | 0:d7f2341ab245 | 208 | int pico_arp_receive(struct pico_frame *f) |
daniele | 0:d7f2341ab245 | 209 | { |
daniele | 0:d7f2341ab245 | 210 | struct pico_arp_hdr *hdr; |
daniele | 0:d7f2341ab245 | 211 | struct pico_arp search, *found, *new = NULL; |
daniele | 0:d7f2341ab245 | 212 | int ret = -1; |
daniele | 0:d7f2341ab245 | 213 | hdr = (struct pico_arp_hdr *) f->net_hdr; |
daniele | 0:d7f2341ab245 | 214 | |
daniele | 0:d7f2341ab245 | 215 | if (!hdr) |
daniele | 0:d7f2341ab245 | 216 | goto end; |
daniele | 0:d7f2341ab245 | 217 | |
daniele | 0:d7f2341ab245 | 218 | |
daniele | 0:d7f2341ab245 | 219 | /* Populate a new arp entry */ |
daniele | 0:d7f2341ab245 | 220 | search.ipv4.addr = hdr->src.addr; |
daniele | 0:d7f2341ab245 | 221 | memcpy(search.eth.addr, hdr->s_mac, PICO_SIZE_ETH); |
daniele | 0:d7f2341ab245 | 222 | |
daniele | 0:d7f2341ab245 | 223 | /* Search for already existing entry */ |
daniele | 0:d7f2341ab245 | 224 | |
daniele | 0:d7f2341ab245 | 225 | found = pico_tree_findKey(&arp_tree,&search); |
daniele | 0:d7f2341ab245 | 226 | if (!found) { |
daniele | 0:d7f2341ab245 | 227 | new = pico_zalloc(sizeof(struct pico_arp)); |
daniele | 0:d7f2341ab245 | 228 | if (!new) |
daniele | 0:d7f2341ab245 | 229 | goto end; |
daniele | 0:d7f2341ab245 | 230 | new->ipv4.addr = hdr->src.addr; |
daniele | 0:d7f2341ab245 | 231 | } |
daniele | 0:d7f2341ab245 | 232 | else if (found->arp_status == PICO_ARP_STATUS_STALE) { |
daniele | 0:d7f2341ab245 | 233 | /* Replace if stale */ |
daniele | 0:d7f2341ab245 | 234 | new = found; |
daniele | 0:d7f2341ab245 | 235 | |
daniele | 0:d7f2341ab245 | 236 | pico_tree_delete(&arp_tree,new); |
daniele | 0:d7f2341ab245 | 237 | } |
daniele | 0:d7f2341ab245 | 238 | |
daniele | 0:d7f2341ab245 | 239 | ret = 0; |
daniele | 0:d7f2341ab245 | 240 | |
daniele | 0:d7f2341ab245 | 241 | if (new) { |
daniele | 0:d7f2341ab245 | 242 | memcpy(new->eth.addr, hdr->s_mac, PICO_SIZE_ETH); |
daniele | 0:d7f2341ab245 | 243 | new->dev = f->dev; |
daniele | 0:d7f2341ab245 | 244 | pico_arp_add_entry(new); |
daniele | 0:d7f2341ab245 | 245 | } |
daniele | 0:d7f2341ab245 | 246 | |
daniele | 0:d7f2341ab245 | 247 | if (hdr->opcode == PICO_ARP_REQUEST) { |
daniele | 0:d7f2341ab245 | 248 | struct pico_ip4 me; |
daniele | 0:d7f2341ab245 | 249 | struct pico_eth_hdr *eh = (struct pico_eth_hdr *)f->datalink_hdr; |
daniele | 0:d7f2341ab245 | 250 | struct pico_device *link_dev; |
daniele | 0:d7f2341ab245 | 251 | me.addr = hdr->dst.addr; |
daniele | 0:d7f2341ab245 | 252 | |
daniele | 0:d7f2341ab245 | 253 | link_dev = pico_ipv4_link_find(&me); |
daniele | 0:d7f2341ab245 | 254 | if (link_dev != f->dev) |
daniele | 0:d7f2341ab245 | 255 | goto end; |
daniele | 0:d7f2341ab245 | 256 | |
daniele | 0:d7f2341ab245 | 257 | hdr->opcode = PICO_ARP_REPLY; |
daniele | 0:d7f2341ab245 | 258 | memcpy(hdr->d_mac, hdr->s_mac, PICO_SIZE_ETH); |
daniele | 0:d7f2341ab245 | 259 | memcpy(hdr->s_mac, f->dev->eth->mac.addr, PICO_SIZE_ETH); |
daniele | 0:d7f2341ab245 | 260 | hdr->dst.addr = hdr->src.addr; |
daniele | 0:d7f2341ab245 | 261 | hdr->src.addr = me.addr; |
daniele | 0:d7f2341ab245 | 262 | |
daniele | 0:d7f2341ab245 | 263 | /* Prepare eth header for arp reply */ |
daniele | 0:d7f2341ab245 | 264 | memcpy(eh->daddr, eh->saddr, PICO_SIZE_ETH); |
daniele | 0:d7f2341ab245 | 265 | memcpy(eh->saddr, f->dev->eth->mac.addr, PICO_SIZE_ETH); |
daniele | 0:d7f2341ab245 | 266 | f->start = f->datalink_hdr; |
daniele | 0:d7f2341ab245 | 267 | f->len = PICO_SIZE_ETHHDR + PICO_SIZE_ARPHDR; |
daniele | 0:d7f2341ab245 | 268 | f->dev->send(f->dev, f->start, f->len); |
daniele | 0:d7f2341ab245 | 269 | } |
daniele | 0:d7f2341ab245 | 270 | |
daniele | 0:d7f2341ab245 | 271 | #ifdef DEBUG_ARG |
daniele | 0:d7f2341ab245 | 272 | dbg_arp(); |
daniele | 0:d7f2341ab245 | 273 | #endif |
daniele | 0:d7f2341ab245 | 274 | |
daniele | 0:d7f2341ab245 | 275 | end: |
daniele | 0:d7f2341ab245 | 276 | pico_frame_discard(f); |
daniele | 0:d7f2341ab245 | 277 | return ret; |
daniele | 0:d7f2341ab245 | 278 | } |
daniele | 0:d7f2341ab245 | 279 | |
daniele | 0:d7f2341ab245 | 280 | int pico_arp_query(struct pico_device *dev, struct pico_ip4 *dst) |
daniele | 0:d7f2341ab245 | 281 | { |
daniele | 0:d7f2341ab245 | 282 | struct pico_frame *q = pico_frame_alloc(PICO_SIZE_ETHHDR + PICO_SIZE_ARPHDR); |
daniele | 0:d7f2341ab245 | 283 | struct pico_eth_hdr *eh; |
daniele | 0:d7f2341ab245 | 284 | struct pico_arp_hdr *ah; |
daniele | 0:d7f2341ab245 | 285 | struct pico_ip4 *src; |
daniele | 0:d7f2341ab245 | 286 | int ret; |
daniele | 0:d7f2341ab245 | 287 | |
daniele | 0:d7f2341ab245 | 288 | src = pico_ipv4_source_find(dst); |
daniele | 0:d7f2341ab245 | 289 | if (!src) |
daniele | 0:d7f2341ab245 | 290 | return -1; |
daniele | 0:d7f2341ab245 | 291 | |
daniele | 0:d7f2341ab245 | 292 | arp_dbg("QUERY: %08x\n", dst->addr); |
daniele | 0:d7f2341ab245 | 293 | |
daniele | 0:d7f2341ab245 | 294 | if (!q) |
daniele | 0:d7f2341ab245 | 295 | return -1; |
daniele | 0:d7f2341ab245 | 296 | eh = (struct pico_eth_hdr *)q->start; |
daniele | 0:d7f2341ab245 | 297 | ah = (struct pico_arp_hdr *) (q->start + PICO_SIZE_ETHHDR); |
daniele | 0:d7f2341ab245 | 298 | |
daniele | 0:d7f2341ab245 | 299 | /* Fill eth header */ |
daniele | 0:d7f2341ab245 | 300 | memcpy(eh->saddr, dev->eth->mac.addr, PICO_SIZE_ETH); |
daniele | 0:d7f2341ab245 | 301 | memcpy(eh->daddr, PICO_ETHADDR_ALL, PICO_SIZE_ETH); |
daniele | 0:d7f2341ab245 | 302 | eh->proto = PICO_IDETH_ARP; |
daniele | 0:d7f2341ab245 | 303 | |
daniele | 0:d7f2341ab245 | 304 | /* Fill arp header */ |
daniele | 0:d7f2341ab245 | 305 | ah->htype = PICO_ARP_HTYPE_ETH; |
daniele | 0:d7f2341ab245 | 306 | ah->ptype = PICO_IDETH_IPV4; |
daniele | 0:d7f2341ab245 | 307 | ah->hsize = PICO_SIZE_ETH; |
daniele | 0:d7f2341ab245 | 308 | ah->psize = PICO_SIZE_IP4; |
daniele | 0:d7f2341ab245 | 309 | ah->opcode = PICO_ARP_REQUEST; |
daniele | 0:d7f2341ab245 | 310 | memcpy(ah->s_mac, dev->eth->mac.addr, PICO_SIZE_ETH); |
daniele | 0:d7f2341ab245 | 311 | ah->src.addr = src->addr; |
daniele | 0:d7f2341ab245 | 312 | ah->dst.addr = dst->addr; |
daniele | 0:d7f2341ab245 | 313 | arp_dbg("Sending arp query.\n"); |
daniele | 0:d7f2341ab245 | 314 | ret = dev->send(dev, q->start, q->len); |
daniele | 0:d7f2341ab245 | 315 | pico_frame_discard(q); |
daniele | 0:d7f2341ab245 | 316 | return ret; |
daniele | 0:d7f2341ab245 | 317 | } |