source: mainline/uspace/srv/net/inetsrv/ndp.c@ ca48672

Last change on this file since ca48672 was b4edc96, checked in by Jiri Svoboda <jiri@…>, 4 years ago

Rename and move addr48_t to eth_addr_t

  • Property mode set to 100644
File size: 5.0 KB
RevLine 
[08ed137]1/*
[b4edc96]2 * Copyright (c) 2021 Jiri Svoboda
[08ed137]3 * Copyright (c) 2013 Antonin Steinhauser
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/** @addtogroup ethip
31 * @{
32 */
33/**
34 * @file
35 * @brief
36 */
37
38#include <errno.h>
[b4edc96]39#include <inet/eth_addr.h>
40#include <io/log.h>
[08ed137]41#include <mem.h>
[38d150e]42#include <stdlib.h>
[08ed137]43#include "ntrans.h"
44#include "addrobj.h"
45#include "pdu.h"
46#include "inet_link.h"
47#include "ndp.h"
48
49/** Time to wait for NDP reply in microseconds */
50#define NDP_REQUEST_TIMEOUT (3 * 1000 * 1000)
51
52static addr128_t solicited_node_ip =
[1433ecda]53 { 0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01, 0xff, 0, 0, 0 };
[08ed137]54
[1d94e21]55/** Compute solicited node IPv6 multicast address from target IPv6 address
56 *
57 * @param ip_addr Target IPv6 address
58 * @param ip_solicited Solicited IPv6 address to be assigned
59 *
60 */
[08ed137]61static void ndp_solicited_node_ip(addr128_t ip_addr,
62 addr128_t ip_solicited)
63{
64 memcpy(ip_solicited, solicited_node_ip, 13);
65 memcpy(ip_solicited + 13, ip_addr + 13, 3);
66}
67
[b7fd2a0]68static errno_t ndp_send_packet(inet_link_t *link, ndp_packet_t *packet)
[08ed137]69{
70 inet_dgram_t dgram;
71 ndp_pdu_encode(packet, &dgram);
[a35b458]72
[f05edcb]73 inet_link_send_dgram6(link, &packet->target_hw_addr, &dgram,
[08ed137]74 IP_PROTO_ICMPV6, INET6_HOP_LIMIT_MAX, 0);
[a35b458]75
[08ed137]76 free(dgram.data);
[a35b458]77
[08ed137]78 return EOK;
79}
80
[b7fd2a0]81static errno_t ndp_router_advertisement(inet_dgram_t *dgram, inet_addr_t *router)
[08ed137]82{
83 // FIXME TODO
84 return ENOTSUP;
85}
86
[b7fd2a0]87errno_t ndp_received(inet_dgram_t *dgram)
[08ed137]88{
[1d94e21]89 log_msg(LOG_DEFAULT, LVL_DEBUG, "ndp_received()");
[a35b458]90
[08ed137]91 ndp_packet_t packet;
[b7fd2a0]92 errno_t rc = ndp_pdu_decode(dgram, &packet);
[08ed137]93 if (rc != EOK)
94 return rc;
[a35b458]95
[08ed137]96 inet_addr_t sender;
97 inet_addr_set6(packet.sender_proto_addr, &sender);
[a35b458]98
[08ed137]99 inet_addr_t target;
100 inet_addr_set6(packet.target_proto_addr, &target);
[a35b458]101
[08ed137]102 inet_addrobj_t *laddr;
[a35b458]103
[1d94e21]104 log_msg(LOG_DEFAULT, LVL_DEBUG, "NDP PDU decoded; opcode: %d",
105 packet.opcode);
[a35b458]106
[08ed137]107 switch (packet.opcode) {
108 case ICMPV6_NEIGHBOUR_SOLICITATION:
109 laddr = inet_addrobj_find(&target, iaf_addr);
110 if (laddr != NULL) {
111 rc = ntrans_add(packet.sender_proto_addr,
[f05edcb]112 &packet.sender_hw_addr);
[08ed137]113 if (rc != EOK)
114 return rc;
[a35b458]115
[08ed137]116 ndp_packet_t reply;
[a35b458]117
[08ed137]118 reply.opcode = ICMPV6_NEIGHBOUR_ADVERTISEMENT;
[d5ed54b]119 reply.sender_hw_addr = laddr->ilink->mac;
[08ed137]120 addr128(packet.target_proto_addr, reply.sender_proto_addr);
[d5ed54b]121 reply.target_hw_addr = packet.sender_hw_addr;
[08ed137]122 addr128(packet.sender_proto_addr, reply.target_proto_addr);
[a35b458]123
[08ed137]124 ndp_send_packet(laddr->ilink, &reply);
125 }
[a35b458]126
[08ed137]127 break;
128 case ICMPV6_NEIGHBOUR_ADVERTISEMENT:
129 laddr = inet_addrobj_find(&dgram->dest, iaf_addr);
130 if (laddr != NULL)
131 return ntrans_add(packet.sender_proto_addr,
[f05edcb]132 &packet.sender_hw_addr);
[a35b458]133
[08ed137]134 break;
135 case ICMPV6_ROUTER_ADVERTISEMENT:
136 return ndp_router_advertisement(dgram, &sender);
137 default:
138 return ENOTSUP;
139 }
[a35b458]140
[08ed137]141 return EOK;
142}
143
[1d94e21]144/** Translate IPv6 to MAC address
145 *
146 * @param src Source IPv6 address
147 * @param dest Destination IPv6 address
148 * @param mac Target MAC address to be assigned
149 * @param link Network interface
150 *
151 * @return EOK on success
152 * @return ENOENT when NDP translation failed
153 *
154 */
[b4edc96]155errno_t ndp_translate(addr128_t src_addr, addr128_t ip_addr, eth_addr_t *mac_addr,
[08ed137]156 inet_link_t *ilink)
157{
158 if (!ilink->mac_valid) {
159 /* The link does not support NDP */
160 memset(mac_addr, 0, 6);
161 return EOK;
162 }
[a35b458]163
[b7fd2a0]164 errno_t rc = ntrans_lookup(ip_addr, mac_addr);
[08ed137]165 if (rc == EOK)
166 return EOK;
[a35b458]167
[08ed137]168 ndp_packet_t packet;
[a35b458]169
[08ed137]170 packet.opcode = ICMPV6_NEIGHBOUR_SOLICITATION;
[d5ed54b]171 packet.sender_hw_addr = ilink->mac;
[08ed137]172 addr128(src_addr, packet.sender_proto_addr);
173 addr128(ip_addr, packet.solicited_ip);
[b4edc96]174 eth_addr_solicited_node(ip_addr, &packet.target_hw_addr);
[08ed137]175 ndp_solicited_node_ip(ip_addr, packet.target_proto_addr);
[a35b458]176
[08ed137]177 rc = ndp_send_packet(ilink, &packet);
178 if (rc != EOK)
179 return rc;
[a35b458]180
[08ed137]181 (void) ntrans_wait_timeout(NDP_REQUEST_TIMEOUT);
[a35b458]182
[08ed137]183 return ntrans_lookup(ip_addr, mac_addr);
184}
Note: See TracBrowser for help on using the repository browser.