HelenOS sources
This source file includes following definitions.
- ndp_solicited_node_ip
- ndp_send_packet
- ndp_router_advertisement
- ndp_received
- ndp_translate
#include <errno.h>
#include <inet/eth_addr.h>
#include <io/log.h>
#include <mem.h>
#include <stdlib.h>
#include "ntrans.h"
#include "addrobj.h"
#include "pdu.h"
#include "inet_link.h"
#include "ndp.h"
#define NDP_REQUEST_TIMEOUT (3 * 1000 * 1000)
static addr128_t solicited_node_ip =
{ 0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01, 0xff, 0, 0, 0 };
static void ndp_solicited_node_ip(addr128_t ip_addr,
addr128_t ip_solicited)
{
memcpy(ip_solicited, solicited_node_ip, 13);
memcpy(ip_solicited + 13, ip_addr + 13, 3);
}
static errno_t ndp_send_packet(inet_link_t *link, ndp_packet_t *packet)
{
inet_dgram_t dgram;
ndp_pdu_encode(packet, &dgram);
inet_link_send_dgram6(link, &packet->target_hw_addr, &dgram,
IP_PROTO_ICMPV6, INET6_HOP_LIMIT_MAX, 0);
free(dgram.data);
return EOK;
}
static errno_t ndp_router_advertisement(inet_dgram_t *dgram, inet_addr_t *router)
{
return ENOTSUP;
}
errno_t ndp_received(inet_dgram_t *dgram)
{
log_msg(LOG_DEFAULT, LVL_DEBUG, "ndp_received()");
ndp_packet_t packet;
errno_t rc = ndp_pdu_decode(dgram, &packet);
if (rc != EOK)
return rc;
inet_addr_t sender;
inet_addr_set6(packet.sender_proto_addr, &sender);
inet_addr_t target;
inet_addr_set6(packet.target_proto_addr, &target);
inet_addrobj_t *laddr;
log_msg(LOG_DEFAULT, LVL_DEBUG, "NDP PDU decoded; opcode: %d",
packet.opcode);
switch (packet.opcode) {
case ICMPV6_NEIGHBOUR_SOLICITATION:
laddr = inet_addrobj_find(&target, iaf_addr);
if (laddr != NULL) {
rc = ntrans_add(packet.sender_proto_addr,
&packet.sender_hw_addr);
if (rc != EOK)
return rc;
ndp_packet_t reply;
reply.opcode = ICMPV6_NEIGHBOUR_ADVERTISEMENT;
reply.sender_hw_addr = laddr->ilink->mac;
addr128(packet.target_proto_addr, reply.sender_proto_addr);
reply.target_hw_addr = packet.sender_hw_addr;
addr128(packet.sender_proto_addr, reply.target_proto_addr);
ndp_send_packet(laddr->ilink, &reply);
}
break;
case ICMPV6_NEIGHBOUR_ADVERTISEMENT:
laddr = inet_addrobj_find(&dgram->dest, iaf_addr);
if (laddr != NULL)
return ntrans_add(packet.sender_proto_addr,
&packet.sender_hw_addr);
break;
case ICMPV6_ROUTER_ADVERTISEMENT:
return ndp_router_advertisement(dgram, &sender);
default:
return ENOTSUP;
}
return EOK;
}
errno_t ndp_translate(addr128_t src_addr, addr128_t ip_addr, eth_addr_t *mac_addr,
inet_link_t *ilink)
{
if (!ilink->mac_valid) {
memset(mac_addr, 0, 6);
return EOK;
}
errno_t rc = ntrans_lookup(ip_addr, mac_addr);
if (rc == EOK)
return EOK;
ndp_packet_t packet;
packet.opcode = ICMPV6_NEIGHBOUR_SOLICITATION;
packet.sender_hw_addr = ilink->mac;
addr128(src_addr, packet.sender_proto_addr);
addr128(ip_addr, packet.solicited_ip);
eth_addr_solicited_node(ip_addr, &packet.target_hw_addr);
ndp_solicited_node_ip(ip_addr, packet.target_proto_addr);
rc = ndp_send_packet(ilink, &packet);
if (rc != EOK)
return rc;
(void) ntrans_wait_timeout(NDP_REQUEST_TIMEOUT);
return ntrans_lookup(ip_addr, mac_addr);
}
HelenOS homepage, sources at GitHub