Fabien Chouteau | 1a0ca1e | 2011-08-03 12:52:54 +0200 | [diff] [blame] | 1 | /* |
| 2 | * ARP table |
| 3 | * |
| 4 | * Copyright (c) 2011 AdaCore |
| 5 | * |
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
| 7 | * of this software and associated documentation files (the "Software"), to deal |
| 8 | * in the Software without restriction, including without limitation the rights |
| 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 10 | * copies of the Software, and to permit persons to whom the Software is |
| 11 | * furnished to do so, subject to the following conditions: |
| 12 | * |
| 13 | * The above copyright notice and this permission notice shall be included in |
| 14 | * all copies or substantial portions of the Software. |
| 15 | * |
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| 22 | * THE SOFTWARE. |
| 23 | */ |
| 24 | |
Peter Maydell | 7df7482 | 2016-01-29 17:49:59 +0000 | [diff] [blame] | 25 | #include "qemu/osdep.h" |
Fabien Chouteau | 1a0ca1e | 2011-08-03 12:52:54 +0200 | [diff] [blame] | 26 | #include "slirp.h" |
| 27 | |
Jan Kiszka | 5a371a2 | 2011-08-05 12:51:11 +0200 | [diff] [blame] | 28 | void arp_table_add(Slirp *slirp, uint32_t ip_addr, uint8_t ethaddr[ETH_ALEN]) |
Fabien Chouteau | 1a0ca1e | 2011-08-03 12:52:54 +0200 | [diff] [blame] | 29 | { |
Jan Kiszka | 5a371a2 | 2011-08-05 12:51:11 +0200 | [diff] [blame] | 30 | const uint32_t broadcast_addr = |
Fabien Chouteau | 1a0ca1e | 2011-08-03 12:52:54 +0200 | [diff] [blame] | 31 | ~slirp->vnetwork_mask.s_addr | slirp->vnetwork_addr.s_addr; |
| 32 | ArpTable *arptbl = &slirp->arp_table; |
| 33 | int i; |
| 34 | |
| 35 | DEBUG_CALL("arp_table_add"); |
Alexey Kardashevskiy | 8ee2022 | 2018-03-13 15:49:44 +1100 | [diff] [blame] | 36 | DEBUG_ARG("ip = %s", inet_ntoa((struct in_addr){.s_addr = ip_addr})); |
Fabien Chouteau | 1a0ca1e | 2011-08-03 12:52:54 +0200 | [diff] [blame] | 37 | DEBUG_ARGS((dfd, " hw addr = %02x:%02x:%02x:%02x:%02x:%02x\n", |
| 38 | ethaddr[0], ethaddr[1], ethaddr[2], |
| 39 | ethaddr[3], ethaddr[4], ethaddr[5])); |
| 40 | |
Samuel Thibault | 959e414 | 2014-05-14 03:13:09 +0200 | [diff] [blame] | 41 | if (ip_addr == 0 || ip_addr == 0xffffffff || ip_addr == broadcast_addr) { |
Fabien Chouteau | 1a0ca1e | 2011-08-03 12:52:54 +0200 | [diff] [blame] | 42 | /* Do not register broadcast addresses */ |
| 43 | return; |
| 44 | } |
| 45 | |
| 46 | /* Search for an entry */ |
| 47 | for (i = 0; i < ARP_TABLE_SIZE; i++) { |
| 48 | if (arptbl->table[i].ar_sip == ip_addr) { |
| 49 | /* Update the entry */ |
| 50 | memcpy(arptbl->table[i].ar_sha, ethaddr, ETH_ALEN); |
| 51 | return; |
| 52 | } |
| 53 | } |
| 54 | |
| 55 | /* No entry found, create a new one */ |
| 56 | arptbl->table[arptbl->next_victim].ar_sip = ip_addr; |
| 57 | memcpy(arptbl->table[arptbl->next_victim].ar_sha, ethaddr, ETH_ALEN); |
| 58 | arptbl->next_victim = (arptbl->next_victim + 1) % ARP_TABLE_SIZE; |
| 59 | } |
| 60 | |
Jan Kiszka | 5a371a2 | 2011-08-05 12:51:11 +0200 | [diff] [blame] | 61 | bool arp_table_search(Slirp *slirp, uint32_t ip_addr, |
Fabien Chouteau | 1a0ca1e | 2011-08-03 12:52:54 +0200 | [diff] [blame] | 62 | uint8_t out_ethaddr[ETH_ALEN]) |
| 63 | { |
Jan Kiszka | 5a371a2 | 2011-08-05 12:51:11 +0200 | [diff] [blame] | 64 | const uint32_t broadcast_addr = |
Fabien Chouteau | 1a0ca1e | 2011-08-03 12:52:54 +0200 | [diff] [blame] | 65 | ~slirp->vnetwork_mask.s_addr | slirp->vnetwork_addr.s_addr; |
| 66 | ArpTable *arptbl = &slirp->arp_table; |
| 67 | int i; |
| 68 | |
| 69 | DEBUG_CALL("arp_table_search"); |
Alexey Kardashevskiy | 8ee2022 | 2018-03-13 15:49:44 +1100 | [diff] [blame] | 70 | DEBUG_ARG("ip = %s", inet_ntoa((struct in_addr){.s_addr = ip_addr})); |
Fabien Chouteau | 1a0ca1e | 2011-08-03 12:52:54 +0200 | [diff] [blame] | 71 | |
Fabien Chouteau | 1a0ca1e | 2011-08-03 12:52:54 +0200 | [diff] [blame] | 72 | /* If broadcast address */ |
Jan Kiszka | 5a371a2 | 2011-08-05 12:51:11 +0200 | [diff] [blame] | 73 | if (ip_addr == 0xffffffff || ip_addr == broadcast_addr) { |
Fabien Chouteau | 1a0ca1e | 2011-08-03 12:52:54 +0200 | [diff] [blame] | 74 | /* return Ethernet broadcast address */ |
| 75 | memset(out_ethaddr, 0xff, ETH_ALEN); |
| 76 | return 1; |
| 77 | } |
| 78 | |
| 79 | for (i = 0; i < ARP_TABLE_SIZE; i++) { |
Jan Kiszka | 5a371a2 | 2011-08-05 12:51:11 +0200 | [diff] [blame] | 80 | if (arptbl->table[i].ar_sip == ip_addr) { |
Fabien Chouteau | 1a0ca1e | 2011-08-03 12:52:54 +0200 | [diff] [blame] | 81 | memcpy(out_ethaddr, arptbl->table[i].ar_sha, ETH_ALEN); |
| 82 | DEBUG_ARGS((dfd, " found hw addr = %02x:%02x:%02x:%02x:%02x:%02x\n", |
| 83 | out_ethaddr[0], out_ethaddr[1], out_ethaddr[2], |
| 84 | out_ethaddr[3], out_ethaddr[4], out_ethaddr[5])); |
| 85 | return 1; |
| 86 | } |
| 87 | } |
| 88 | |
| 89 | return 0; |
| 90 | } |