Guillaume Subiron | 0d6ff71 | 2016-03-15 10:31:19 +0100 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2013 |
| 3 | * Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne. |
| 4 | */ |
| 5 | |
| 6 | #include "qemu/osdep.h" |
| 7 | #include "qemu-common.h" |
| 8 | #include "slirp.h" |
| 9 | |
| 10 | void ndp_table_add(Slirp *slirp, struct in6_addr ip_addr, |
| 11 | uint8_t ethaddr[ETH_ALEN]) |
| 12 | { |
| 13 | NdpTable *ndp_table = &slirp->ndp_table; |
| 14 | int i; |
| 15 | |
| 16 | DEBUG_CALL("ndp_table_add"); |
| 17 | #if !defined(_WIN32) || (_WIN32_WINNT >= 0x0600) |
| 18 | char addrstr[INET6_ADDRSTRLEN]; |
| 19 | inet_ntop(AF_INET6, &(ip_addr), addrstr, INET6_ADDRSTRLEN); |
| 20 | DEBUG_ARG("ip = %s", addrstr); |
| 21 | #endif |
| 22 | DEBUG_ARGS((dfd, " hw addr = %02x:%02x:%02x:%02x:%02x:%02x\n", |
| 23 | ethaddr[0], ethaddr[1], ethaddr[2], |
| 24 | ethaddr[3], ethaddr[4], ethaddr[5])); |
| 25 | |
| 26 | if (IN6_IS_ADDR_MULTICAST(&ip_addr) || IN6_IS_ADDR_UNSPECIFIED(&ip_addr)) { |
| 27 | /* Do not register multicast or unspecified addresses */ |
| 28 | DEBUG_CALL(" abort: do not register multicast or unspecified address"); |
| 29 | return; |
| 30 | } |
| 31 | |
| 32 | /* Search for an entry */ |
| 33 | for (i = 0; i < NDP_TABLE_SIZE; i++) { |
| 34 | if (in6_equal(&ndp_table->table[i].ip_addr, &ip_addr)) { |
| 35 | DEBUG_CALL(" already in table: update the entry"); |
| 36 | /* Update the entry */ |
| 37 | memcpy(ndp_table->table[i].eth_addr, ethaddr, ETH_ALEN); |
| 38 | return; |
| 39 | } |
| 40 | } |
| 41 | |
| 42 | /* No entry found, create a new one */ |
| 43 | DEBUG_CALL(" create new entry"); |
| 44 | ndp_table->table[ndp_table->next_victim].ip_addr = ip_addr; |
| 45 | memcpy(ndp_table->table[ndp_table->next_victim].eth_addr, |
| 46 | ethaddr, ETH_ALEN); |
| 47 | ndp_table->next_victim = (ndp_table->next_victim + 1) % NDP_TABLE_SIZE; |
| 48 | } |
| 49 | |
| 50 | bool ndp_table_search(Slirp *slirp, struct in6_addr ip_addr, |
| 51 | uint8_t out_ethaddr[ETH_ALEN]) |
| 52 | { |
| 53 | NdpTable *ndp_table = &slirp->ndp_table; |
| 54 | int i; |
| 55 | |
| 56 | DEBUG_CALL("ndp_table_search"); |
| 57 | #if !defined(_WIN32) || (_WIN32_WINNT >= 0x0600) |
| 58 | char addrstr[INET6_ADDRSTRLEN]; |
| 59 | inet_ntop(AF_INET6, &(ip_addr), addrstr, INET6_ADDRSTRLEN); |
| 60 | DEBUG_ARG("ip = %s", addrstr); |
| 61 | #endif |
| 62 | |
| 63 | assert(!IN6_IS_ADDR_UNSPECIFIED(&ip_addr)); |
| 64 | |
| 65 | /* Multicast address: fec0::abcd:efgh/8 -> 33:33:ab:cd:ef:gh */ |
| 66 | if (IN6_IS_ADDR_MULTICAST(&ip_addr)) { |
| 67 | out_ethaddr[0] = 0x33; out_ethaddr[1] = 0x33; |
| 68 | out_ethaddr[2] = ip_addr.s6_addr[12]; |
| 69 | out_ethaddr[3] = ip_addr.s6_addr[13]; |
| 70 | out_ethaddr[4] = ip_addr.s6_addr[14]; |
| 71 | out_ethaddr[5] = ip_addr.s6_addr[15]; |
| 72 | DEBUG_ARGS((dfd, " multicast addr = %02x:%02x:%02x:%02x:%02x:%02x\n", |
| 73 | out_ethaddr[0], out_ethaddr[1], out_ethaddr[2], |
| 74 | out_ethaddr[3], out_ethaddr[4], out_ethaddr[5])); |
| 75 | return 1; |
| 76 | } |
| 77 | |
| 78 | for (i = 0; i < NDP_TABLE_SIZE; i++) { |
| 79 | if (in6_equal(&ndp_table->table[i].ip_addr, &ip_addr)) { |
| 80 | memcpy(out_ethaddr, ndp_table->table[i].eth_addr, ETH_ALEN); |
| 81 | DEBUG_ARGS((dfd, " found hw addr = %02x:%02x:%02x:%02x:%02x:%02x\n", |
| 82 | out_ethaddr[0], out_ethaddr[1], out_ethaddr[2], |
| 83 | out_ethaddr[3], out_ethaddr[4], out_ethaddr[5])); |
| 84 | return 1; |
| 85 | } |
| 86 | } |
| 87 | |
| 88 | DEBUG_CALL(" ip not found in table"); |
| 89 | return 0; |
| 90 | } |