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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 44c9ef4 was 1d94e21, checked in by Martin Decky <martin@…>, 12 years ago

cherrypick lp:~as-s/helenos/ipv6

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