Open junwushi opened 6 years ago
Could you provide more context related to the error ? It would help a lot if you could connect a debugger to the 6lbr process and get the backtrace of the error.
below that i fixed code with alignment trap issue in /6lbr/core/net/ipv6/uip-nd6.c. it is not better way,please check. /*
*/
/**
/**
/------------------------------------------------------------------/
void uip_log(char *msg);
/------------------------------------------------------------------/ /* @{ / /** \name Pointers to the header structures.
/*@{ Pointers to messages just after icmp header /
/* @} / /* Pointer to ND option /
/* @} /
static uint8_t nd6_opt_offset; / Offset from the end of the icmpv6 header to the option in uip_buf/ static uint8_t nd6_opt_llao; / Pointer to llao option in uip_buf / static uip_ds6_nbr_t nbr; / Pointer to a nbr cache entry/ static uip_ds6_addr_t addr; / Pointer to an interface address */
static uip_ds6_defrt_t *defrt; /* Pointer to a router list entry /
static uip_nd6_opt_prefix_info *nd6_opt_prefix_info; /* Pointer to prefix information option in uip_buf / static uip_ipaddr_t ipaddr;
static uip_ds6_route_info_t *rtinfo; /* Pointer to a route information list entry /
static uip_ds6_prefix_t *prefix; /* Pointer to a prefix list entry /
/------------------------------------------------------------------/ / Copy link-layer address from LLAO option to a word-aligned uip_lladdr_t / static int extract_lladdr_from_llao_aligned(uip_lladdr_t *dest) { if(dest != NULL && nd6_opt_llao != NULL) { memcpy(dest, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], UIP_LLADDR_LEN); return 1; } return 0; }
/------------------------------------------------------------------/ / create a llao / static void create_llao(uint8_t llao, uint8_t type) { llao[UIP_ND6_OPT_TYPE_OFFSET] = type; llao[UIP_ND6_OPT_LEN_OFFSET] = UIP_ND6_OPT_LLAO_LEN >> 3; memcpy(&llao[UIP_ND6_OPT_DATA_OFFSET], &uip_lladdr, UIP_LLADDR_LEN); / padding on some */ memset(&llao[UIP_ND6_OPT_DATA_OFFSET + UIP_LLADDR_LEN], 0, UIP_ND6_OPT_LLAO_LEN - 2 - UIP_LLADDR_LEN); }
/------------------------------------------------------------------/ /**
*/
static void ns_input(void) { uint8_t flags;
uip_ds6_route_t * route;
uip_ipaddr_t tgtipaddr;
PRINTF("Received NS from "); PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINTF(" to "); PRINT6ADDR(&UIP_IP_BUF->destipaddr); PRINTF(" with target address "); PRINT6ADDR((uip_ipaddr_t *) (&UIP_ND6_NS_BUF->tgtipaddr)); PRINTF("\n"); UIP_STAT(++uip_stat.nd6.recv);
if((UIP_IP_BUF->ttl != UIP_ND6_HOP_LIMIT) || (uip_is_addr_mcast(&UIP_ND6_NS_BUF->tgtipaddr)) || (UIP_ICMP_BUF->icode != 0)) { PRINTF("NS received is bad\n"); goto discard; }
/ Options processing / nd6_opt_llao = NULL; nd6_opt_offset = UIP_ND6_NS_LEN; while(uip_l3_icmp_hdr_len + nd6_opt_offset < uip_len) {
if(UIP_ND6_OPT_HDR_BUF->len == 0) {
PRINTF("NS received is bad\n");
goto discard;
}
switch (UIP_ND6_OPT_HDR_BUF->type) {
case UIP_ND6_OPT_SLLAO:
nd6_opt_llao = &uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset];
/* There must be NO option in a DAD NS */
if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
PRINTF("NS received is bad\n");
goto discard;
} else {
uip_lladdr_t lladdr_aligned;
extract_lladdr_from_llao_aligned(&lladdr_aligned);
nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr);
if(nbr == NULL) {
uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned,
0, NBR_STALE, NBR_TABLE_REASON_IPV6_ND, NULL);
} else {
const uip_lladdr_t *lladdr = uip_ds6_nbr_get_ll(nbr);
if(lladdr == NULL) {
goto discard;
}
if(memcmp(&lladdr_aligned, lladdr, UIP_LLADDR_LEN) != 0) {
if(uip_ds6_nbr_update_lladdr(&nbr, &lladdr_aligned) == 0) {
/* failed to update the lladdr */
goto discard;
}
nbr->state = NBR_STALE;
} else {
if(nbr->state == NBR_INCOMPLETE) {
nbr->state = NBR_STALE;
}
}
}
}
break;
default:
PRINTF("ND option not supported in NS");
break;
}
nd6_opt_offset += (UIP_ND6_OPT_HDR_BUF->len << 3);
}
memcpy(&tgtipaddr, &UIP_ND6_NS_BUF->tgtipaddr, sizeof(tgtipaddr)); addr = uip_ds6_addr_lookup(&tgtipaddr);
//ND Proxy implementation if ( addr == NULL ) { if ( (route = uip_ds6_route_lookup(&tgtipaddr)) != NULL ) { if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) { / DAD CASE / uip_create_linklocal_allnodes_mcast(&tgtipaddr); uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, &tgtipaddr); flags = UIP_ND6_NA_FLAG_OVERRIDE; goto create_na; } else { uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &UIP_IP_BUF->srcipaddr); uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, &tgtipaddr); flags = UIP_ND6_NA_FLAG_SOLICITED | UIP_ND6_NA_FLAG_OVERRIDE; goto create_na; } } }
if(addr != NULL) { if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) { / DAD CASE /
if(!uip_is_addr_solicited_node(&UIP_IP_BUF->destipaddr)) {
PRINTF("NS received is bad\n");
goto discard;
}
if(addr->state != ADDR_TENTATIVE) {
uip_create_linklocal_allnodes_mcast(&UIP_IP_BUF->destipaddr);
uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr);
flags = UIP_ND6_NA_FLAG_OVERRIDE;
goto create_na;
} else {
/** \todo if I sent a NS before him, I win */
uip_ds6_dad_failed(addr);
goto discard;
}
goto discard; /* DAD CASE */
}
if(uip_ds6_is_my_addr(&UIP_IP_BUF->srcipaddr)) {
/**
* \NOTE do we do something here? we both are using the same address.
* If we are doing dad, we could cancel it, though we should receive a
* NA in response of DAD NS we sent, hence DAD will fail anyway. If we
* were not doing DAD, it means there is a duplicate in the network!
*/
PRINTF("NS received is bad\n");
goto discard;
}
/* Address resolution case */
if(uip_is_addr_solicited_node(&UIP_IP_BUF->destipaddr)) {
uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &UIP_IP_BUF->srcipaddr);
uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, &tgtipaddr);
flags = UIP_ND6_NA_FLAG_SOLICITED | UIP_ND6_NA_FLAG_OVERRIDE;
goto create_na;
}
/* NUD CASE */
if(uip_ds6_addr_lookup(&UIP_IP_BUF->destipaddr) == addr) {
uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &UIP_IP_BUF->srcipaddr);
uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, &tgtipaddr);
flags = UIP_ND6_NA_FLAG_SOLICITED | UIP_ND6_NA_FLAG_OVERRIDE;
goto create_na;
} else {
PRINTF("NS received is bad\n");
goto discard;
}
} else { goto discard; }
create_na: / If the node is a router it should set R flag in NAs /
flags = flags | UIP_ND6_NA_FLAG_ROUTER;
uip_ext_len = 0; UIP_IP_BUF->vtc = 0x60; UIP_IP_BUF->tcflow = 0; UIP_IP_BUF->flow = 0; UIP_IP_BUF->len[0] = 0; / length will not be more than 255 / UIP_IP_BUF->len[1] = UIP_ICMPH_LEN + UIP_ND6_NA_LEN + UIP_ND6_OPT_LLAO_LEN; UIP_IP_BUF->proto = UIP_PROTO_ICMP6; UIP_IP_BUF->ttl = UIP_ND6_HOP_LIMIT;
UIP_ICMP_BUF->type = ICMP6_NA; UIP_ICMP_BUF->icode = 0;
UIP_ND6_NA_BUF->flagsreserved = flags; memcpy(&UIP_ND6_NA_BUF->tgtipaddr, &tgtipaddr, sizeof(uip_ipaddr_t));
create_llao(&uip_buf[uip_l2_l3_icmp_hdr_len + UIP_ND6_NA_LEN], UIP_ND6_OPT_TLLAO);
UIP_ICMP_BUF->icmpchksum = 0; UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_NA_LEN + UIP_ND6_OPT_LLAO_LEN;
UIP_STAT(++uip_stat.nd6.sent); PRINTF("Sending NA to "); PRINT6ADDR(&UIP_IP_BUF->destipaddr); PRINTF(" from "); PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINTF(" with target address "); PRINT6ADDR(&UIP_ND6_NA_BUF->tgtipaddr); PRINTF("\n"); return;
discard: uip_clear_buf(); return; }
/------------------------------------------------------------------/
void uip_nd6_ns_output(uip_ipaddr_t src, uip_ipaddr_t dest, uip_ipaddr_t * tgt) { uip_ext_len = 0; UIP_IP_BUF->vtc = 0x60; UIP_IP_BUF->tcflow = 0; UIP_IP_BUF->flow = 0; UIP_IP_BUF->proto = UIP_PROTO_ICMP6; UIP_IP_BUF->ttl = UIP_ND6_HOP_LIMIT;
if(dest == NULL) { uip_create_solicited_node(tgt, &UIP_IP_BUF->destipaddr); } else { uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, dest); } UIP_ICMP_BUF->type = ICMP6_NS; UIP_ICMP_BUF->icode = 0; //UIP_ND6_NS_BUF->reserved = 0; memset((char)&UIP_ND6_NS_BUF->reserved,0,4); uip_ipaddr_copy((uip_ipaddr_t ) &UIP_ND6_NS_BUF->tgtipaddr, tgt); UIP_IP_BUF->len[0] = 0; / length will not be more than 255 / /*
(here yes), for Address resolution , MUST */ if(!(uip_ds6_is_my_addr(tgt))) { if(src != NULL) { uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, src); } else { uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr); } if (uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) { PRINTF("Dropping NS due to no suitable source address\n"); uip_clear_buf(); return; } UIP_IP_BUF->len[1] = UIP_ICMPH_LEN + UIP_ND6_NS_LEN + UIP_ND6_OPT_LLAO_LEN;
create_llao(&uip_buf[uip_l2_l3_icmp_hdr_len + UIP_ND6_NS_LEN], UIP_ND6_OPT_SLLAO);
uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_NS_LEN + UIP_ND6_OPT_LLAO_LEN; } else { uip_create_unspecified(&UIP_IP_BUF->srcipaddr); UIP_IP_BUF->len[1] = UIP_ICMPH_LEN + UIP_ND6_NS_LEN; uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_NS_LEN; }
UIP_ICMP_BUF->icmpchksum = 0; UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
UIP_STAT(++uip_stat.nd6.sent); PRINTF("Sending NS to "); PRINT6ADDR(&UIP_IP_BUF->destipaddr); PRINTF(" from "); PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINTF(" with target address "); PRINT6ADDR(tgt); PRINTF("\n"); return; }
/------------------------------------------------------------------/ /**
*/ static void na_input(void) {
uip_ds6_route_t * route;
uint8_t is_llchange; uint8_t is_router; uint8_t is_solicited; uint8_t is_override; uip_lladdr_t lladdr_aligned;
PRINTF("Received NA from "); PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINTF(" to "); PRINT6ADDR(&UIP_IP_BUF->destipaddr); PRINTF(" with target address "); PRINT6ADDR((uip_ipaddr_t *) (&UIP_ND6_NA_BUF->tgtipaddr)); PRINTF("\n"); UIP_STAT(++uip_stat.nd6.recv);
/*
if((UIP_IP_BUF->ttl != UIP_ND6_HOP_LIMIT) || (UIP_ICMP_BUF->icode != 0) || (uip_is_addr_mcast(&UIP_ND6_NA_BUF->tgtipaddr)) || (is_solicited && uip_is_addr_mcast(&UIP_IP_BUF->destipaddr))) { PRINTF("NA received is bad\n"); goto discard; }
/ Options processing: we handle TLLAO, and must ignore others / nd6_opt_offset = UIP_ND6_NA_LEN; nd6_opt_llao = NULL; while(uip_l3_icmp_hdr_len + nd6_opt_offset < uip_len) {
if(UIP_ND6_OPT_HDR_BUF->len == 0) {
PRINTF("NA received is bad\n");
goto discard;
}
switch (UIP_ND6_OPT_HDR_BUF->type) {
case UIP_ND6_OPT_TLLAO:
nd6_opt_llao = (uint8_t *)UIP_ND6_OPT_HDR_BUF;
break;
default:
PRINTF("ND option not supported in NA\n");
break;
}
nd6_opt_offset += (UIP_ND6_OPT_HDR_BUF->len << 3);
}
/ Address Advertisement / if ( (nvm_data.mode & CETIC_MODE_SMART_MULTI_BR) != 0 ) { if (uip_is_addr_mcast(&UIP_IP_BUF->destipaddr) && uip_is_mcast_group_id_all_nodes(&UIP_IP_BUF->destipaddr)) { LOG6LBR_6ADDR(INFO, &UIP_ND6_NA_BUF->tgtipaddr, "Received purge NA for ");
node_info_rm_by_addr(&UIP_ND6_NA_BUF->tgtipaddr);
route = uip_ds6_route_lookup(&UIP_ND6_NA_BUF->tgtipaddr);
if (route != NULL ) {
uip_ds6_route_rm(route);
}
goto discard;
}
}
addr = uip_ds6_addr_lookup(&UIP_ND6_NA_BUF->tgtipaddr); / Message processing, including TLLAO if any / if(addr != NULL) {
if(addr->state == ADDR_TENTATIVE) {
uip_ds6_dad_failed(addr);
}
PRINTF("NA received is bad\n");
goto discard;
} else { const uip_lladdr_t lladdr; nbr = uip_ds6_nbr_lookup(&UIP_ND6_NA_BUF->tgtipaddr); if(nbr == NULL) { goto discard; } lladdr = uip_ds6_nbr_get_ll(nbr); if(lladdr == NULL) { goto discard; } if(nd6_opt_llao != NULL) { is_llchange = memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], lladdr, UIP_LLADDR_LEN); } if(nbr->state == NBR_INCOMPLETE) { if(nd6_opt_llao == NULL || !extract_lladdr_from_llao_aligned(&lladdr_aligned)) { goto discard; } if(uip_ds6_nbr_update_lladdr(&nbr, &lladdr_aligned) == 0) { / failed to update the lladdr */ goto discard; }
/* Note: No need to refresh the state of the nbr here.
* It has already been refreshed upon receiving the unicast IPv6 ND packet.
* See: uip_ds6_nbr_refresh_reachable_state()
*/
if(!is_solicited) {
nbr->state = NBR_STALE;
} else {
nbr->state = NBR_REACHABLE;
nbr->nscount = 0;
stimer_set(&nbr->reachable, UIP_ND6_REACHABLE_TIME / 1000);
}
nbr->isrouter = is_router;
} else { /* NBR is not INCOMPLETE */
if(!is_override && is_llchange) {
if(nbr->state == NBR_REACHABLE) {
nbr->state = NBR_STALE;
}
goto discard;
} else {
/**
* If this is an cache override, or same lladdr, or no llao -
* do updates of nbr states.
*/
if(is_override || !is_llchange || nd6_opt_llao == NULL) {
if(nd6_opt_llao != NULL && is_llchange) {
if(!extract_lladdr_from_llao_aligned(&lladdr_aligned) ||
uip_ds6_nbr_update_lladdr(&nbr, &lladdr_aligned) == 0) {
/* failed to update the lladdr */
goto discard;
}
}
/* Note: No need to refresh the state of the nbr here.
* It has already been refreshed upon receiving the unicast IPv6 ND packet.
* See: uip_ds6_nbr_refresh_reachable_state()
*/
}
}
if(nbr->isrouter && !is_router) {
defrt = uip_ds6_defrt_lookup(&UIP_IP_BUF->srcipaddr);
if(defrt != NULL) {
uip_ds6_defrt_rm(defrt);
}
}
nbr->isrouter = is_router;
}
}
/ The nbr is now reachable, check if we had buffered a pkt for it / /if(nbr->queue_buf_len != 0) { uip_len = nbr->queue_buf_len; memcpy(UIP_IP_BUF, nbr->queue_buf, uip_len); nbr->queue_buf_len = 0; return; }/ if(uip_packetqueue_buflen(&nbr->packethandle) != 0) { uip_len = uip_packetqueue_buflen(&nbr->packethandle); memcpy(UIP_IP_BUF, uip_packetqueue_buf(&nbr->packethandle), uip_len); uip_packetqueue_free(&nbr->packethandle); return; }
discard: uip_clear_buf(); return; }
void send_purge_na(uip_ipaddr_t prefix) { if ( (nvm_data.mode & CETIC_MODE_SMART_MULTI_BR) == 0 ) { return; } LOG6LBR_6ADDR(INFO, prefix, "Sending purge NA for "); uip_ext_len = 0; UIP_IP_BUF->vtc = 0x60; UIP_IP_BUF->tcflow = 0; UIP_IP_BUF->flow = 0; UIP_IP_BUF->len[0] = 0; / length will not be more than 255 */ UIP_IP_BUF->len[1] = UIP_ICMPH_LEN + UIP_ND6_NA_LEN + UIP_ND6_OPT_LLAO_LEN; UIP_IP_BUF->proto = UIP_PROTO_ICMP6; UIP_IP_BUF->ttl = UIP_ND6_HOP_LIMIT;
uip_create_linklocal_allnodes_mcast(&UIP_IP_BUF->destipaddr);
uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, prefix);
UIP_ICMP_BUF->type = ICMP6_NA;
UIP_ICMP_BUF->icode = 0;
UIP_ND6_NA_BUF->flagsreserved = UIP_ND6_NA_FLAG_OVERRIDE;
memcpy(&UIP_ND6_NA_BUF->tgtipaddr, prefix, sizeof(uip_ipaddr_t));
create_llao(&uip_buf[uip_l2_l3_icmp_hdr_len + UIP_ND6_NA_LEN],
UIP_ND6_OPT_TLLAO);
UIP_ICMP_BUF->icmpchksum = 0;
UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
uip_len =
UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_NA_LEN + UIP_ND6_OPT_LLAO_LEN;
UIP_STAT(++uip_stat.nd6.sent);
PRINTF("Sending Unsolicited NA to ");
PRINT6ADDR(&UIP_IP_BUF->destipaddr);
PRINTF(" from ");
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
PRINTF(" with target address ");
PRINT6ADDR(&UIP_ND6_NA_BUF->tgtipaddr);
PRINTF("\n");
tcpip_ipv6_output();
}
/---------------------------------------------------------------------------/ static void rs_input(void) {
PRINTF("Received RS from "); PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINTF(" to "); PRINT6ADDR(&UIP_IP_BUF->destipaddr); PRINTF("\n"); UIP_STAT(++uip_stat.nd6.recv);
/*
if the NA is solicited, dest must not be multicast */ if((UIP_IP_BUF->ttl != UIP_ND6_HOP_LIMIT) || (UIP_ICMP_BUF->icode != 0)) { PRINTF("RS received is bad\n"); goto discard; }
/ Only valid option is Source Link-Layer Address option any thing else is discarded / nd6_opt_offset = UIP_ND6_RS_LEN; nd6_opt_llao = NULL;
while(uip_l3_icmp_hdr_len + nd6_opt_offset < uip_len) {
if(UIP_ND6_OPT_HDR_BUF->len == 0) { PRINTF("RS received is bad\n"); goto discard; }
switch (UIP_ND6_OPT_HDR_BUF->type) { case UIP_ND6_OPT_SLLAO: nd6_opt_llao = (uint8_t )UIP_ND6_OPT_HDR_BUF; break; default: PRINTF("ND option not supported in RS\n"); break; } nd6_opt_offset += (UIP_ND6_OPT_HDR_BUF->len << 3); } / Options processing: only SLLAO */ if(nd6_opt_llao != NULL) {
if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) { PRINTF("RS received is bad\n"); goto discard; } else {
uip_lladdr_t lladdr_aligned; extract_lladdr_from_llao_aligned(&lladdr_aligned); if((nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr)) == NULL) { / we need to add the neighbor / uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned, 0, NBR_STALE, NBR_TABLE_REASON_IPV6_ND, NULL); } else { / If LL address changed, set neighbor state to stale / const uip_lladdr_t lladdr = uip_ds6_nbr_get_ll(nbr); if(lladdr == NULL) { goto discard; } if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], lladdr, UIP_LLADDR_LEN) != 0) { uip_ds6_nbr_t nbr_data; nbr_data = nbr; uip_ds6_nbr_rm(nbr); nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned, 0, NBR_STALE, NBR_TABLE_REASON_IPV6_ND, NULL); nbr->reachable = nbr_data.reachable; nbr->sendns = nbr_data.sendns; nbr->nscount = nbr_data.nscount; } nbr->isrouter = 0; }
}
}
/ Schedule a sollicited RA / uip_ds6_send_ra_sollicited();
discard: uip_clear_buf(); return; }
/---------------------------------------------------------------------------/ void uip_nd6_ra_output(uip_ipaddr_t * dest) {
UIP_IP_BUF->vtc = 0x60; UIP_IP_BUF->tcflow = 0; UIP_IP_BUF->flow = 0; UIP_IP_BUF->proto = UIP_PROTO_ICMP6; UIP_IP_BUF->ttl = UIP_ND6_HOP_LIMIT;
if(dest == NULL) { uip_create_linklocal_allnodes_mcast(&UIP_IP_BUF->destipaddr); } else { / For sollicited RA / uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, dest); } uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr);
UIP_ICMP_BUF->type = ICMP6_RA; UIP_ICMP_BUF->icode = 0;
UIP_ND6_RA_BUF->cur_ttl = uip_ds6_if.cur_hop_limit;
UIP_ND6_RA_BUF->flags_reserved = (UIP_ND6_M_FLAG << 7) | (UIP_ND6_O_FLAG << 6);
UIP_ND6_RA_BUF->router_lifetime = uip_htons(UIP_ND6_ROUTER_LIFETIME); //UIP_ND6_RA_BUF->reachable_time = uip_htonl(uip_ds6_if.reachable_time); //UIP_ND6_RA_BUF->retrans_timer = uip_htonl(uip_ds6_if.retrans_timer); memset((char)&UIP_ND6_RA_BUF->reachable_time,0,4); memset((char)&UIP_ND6_RA_BUF->retrans_timer,0,4);
//UIP_ND6_RA_BUF->reachable_time = 0; //UIP_ND6_RA_BUF->retrans_timer = 0;
uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_RA_LEN; nd6_opt_offset = UIP_ND6_RA_LEN;
/ Prefix list / for(prefix = uip_ds6_prefix_list; prefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB; prefix++) { if((prefix->isused) && (prefix->advertise)) { UIP_ND6_OPT_PREFIX_BUF->type = UIP_ND6_OPT_PREFIX_INFO; UIP_ND6_OPT_PREFIX_BUF->len = UIP_ND6_OPT_PREFIX_INFO_LEN / 8; UIP_ND6_OPT_PREFIX_BUF->preflen = prefix->length; UIP_ND6_OPT_PREFIX_BUF->flagsreserved1 = prefix->l_a_reserved; uint32_t ttime=uip_htonl(prefix->vlifetime); memcpy((char)&UIP_ND6_OPT_PREFIX_BUF->validlt,(char)&ttime,4); //UIP_ND6_OPT_PREFIX_BUF->validlt = uip_htonl(prefix->vlifetime); ttime=uip_htonl(prefix->plifetime); memcpy((char)&UIP_ND6_OPT_PREFIX_BUF->preferredlt,(char)&ttime,4); //UIP_ND6_OPT_PREFIX_BUF->preferredlt = uip_htonl(prefix->plifetime); ttime=0; memcpy((char)&UIP_ND6_OPT_PREFIX_BUF->reserved2,(char)&ttime,4); //UIP_ND6_OPT_PREFIX_BUF->reserved2 = 0; uip_ipaddr_copy(&(UIP_ND6_OPT_PREFIX_BUF->prefix), &(prefix->ipaddr)); nd6_opt_offset += UIP_ND6_OPT_PREFIX_INFO_LEN; uip_len += UIP_ND6_OPT_PREFIX_INFO_LEN; } }
/ Source link-layer option / create_llao((uint8_t *)UIP_ND6_OPT_HDR_BUF, UIP_ND6_OPT_SLLAO);
uip_len += UIP_ND6_OPT_LLAO_LEN; nd6_opt_offset += UIP_ND6_OPT_LLAO_LEN;
/ MTU / UIP_ND6_OPT_MTU_BUF->type = UIP_ND6_OPT_MTU; UIP_ND6_OPT_MTU_BUF->len = UIP_ND6_OPT_MTU_LEN >> 3; UIP_ND6_OPT_MTU_BUF->reserved = 0; //UIP_ND6_OPT_MTU_BUF->mtu = uip_htonl(uip_ds6_if.link_mtu); uint32_t mtu=1500; //UIP_ND6_OPT_MTU_BUF->mtu = uip_htonl(1500); memcpy((char)&UIP_ND6_OPT_MTU_BUF->mtu,(char)&mtu,4); uip_len += UIP_ND6_OPT_MTU_LEN; nd6_opt_offset += UIP_ND6_OPT_MTU_LEN;
for(rtinfo = uip_ds6_route_info_list; rtinfo < uip_ds6_route_info_list + UIP_DS6_ROUTE_INFO_NB; rtinfo++) { if((rtinfo->isused)) { UIP_ND6_OPT_ROUTE_BUF->type = UIP_ND6_OPT_ROUTE_INFO; UIP_ND6_OPT_ROUTE_BUF->len =(rtinfo->length >> 6) + 1 ; UIP_ND6_OPT_ROUTE_BUF->preflen = rtinfo->length; UIP_ND6_OPT_ROUTE_BUF->flagsreserved = rtinfo->flags; uint32_t ttime=uip_htonl(rtinfo->lifetime); memcpy((char)&UIP_ND6_OPT_ROUTE_BUF->rlifetime,(char)&ttime,4); //UIP_ND6_OPT_ROUTE_BUF->rlifetime = uip_htonl(rtinfo->lifetime); uip_ipaddr_copy(&(UIP_ND6_OPT_ROUTE_BUF->prefix), &(rtinfo->ipaddr)); nd6_opt_offset += ((rtinfo->length >> 6) + 1)<<3; uip_len += ((rtinfo->length >> 6) + 1)<<3; } }
if(uip_nameserver_count() > 0) { uint8_t i = 0; uip_ipaddr_t ip = &UIP_ND6_OPT_RDNSS_BUF->ip; uip_ipaddr_t dns = NULL; UIP_ND6_OPT_RDNSS_BUF->type = UIP_ND6_OPT_RDNSS; UIP_ND6_OPT_RDNSS_BUF->reserved = 0; UIP_ND6_OPT_RDNSS_BUF->lifetime = uip_nameserver_next_expiration(); if(UIP_ND6_OPT_RDNSS_BUF->lifetime != UIP_NAMESERVER_INFINITE_LIFETIME) { UIP_ND6_OPT_RDNSS_BUF->lifetime -= clock_seconds(); } while((dns = uip_nameserver_get(i)) != NULL) { uip_ipaddr_copy(ip++, dns); i++; } UIP_ND6_OPT_RDNSS_BUF->len = UIP_ND6_OPT_RDNSS_LEN + (i << 1); PRINTF("%d nameservers reported\n", i); uip_len += UIP_ND6_OPT_RDNSS_BUF->len << 3; nd6_opt_offset += UIP_ND6_OPT_RDNSS_BUF->len << 3; }
UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
/ICMP checksum / UIP_ICMP_BUF->icmpchksum = 0; UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
UIP_STAT(++uip_stat.nd6.sent); PRINTF("Sending RA to "); PRINT6ADDR(&UIP_IP_BUF->destipaddr); PRINTF(" from "); PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINTF("\n"); return; }
/---------------------------------------------------------------------------/ void uip_nd6_rs_output(void) { UIP_IP_BUF->vtc = 0x60; UIP_IP_BUF->tcflow = 0; UIP_IP_BUF->flow = 0; UIP_IP_BUF->proto = UIP_PROTO_ICMP6; UIP_IP_BUF->ttl = UIP_ND6_HOP_LIMIT; uip_create_linklocal_allrouters_mcast(&UIP_IP_BUF->destipaddr); uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr); UIP_ICMP_BUF->type = ICMP6_RS; UIP_ICMP_BUF->icode = 0; UIP_IP_BUF->len[0] = 0; / length will not be more than 255 /
if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) { UIP_IP_BUF->len[1] = UIP_ICMPH_LEN + UIP_ND6_RS_LEN; uip_len = uip_l3_icmp_hdr_len + UIP_ND6_RS_LEN; } else { uip_len = uip_l3_icmp_hdr_len + UIP_ND6_RS_LEN + UIP_ND6_OPT_LLAO_LEN; UIP_IP_BUF->len[1] = UIP_ICMPH_LEN + UIP_ND6_RS_LEN + UIP_ND6_OPT_LLAO_LEN;
create_llao(&uip_buf[uip_l2_l3_icmp_hdr_len + UIP_ND6_RS_LEN],
UIP_ND6_OPT_SLLAO);
}
UIP_ICMP_BUF->icmpchksum = 0; UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
UIP_STAT(++uip_stat.nd6.sent); PRINTF("Sendin RS to "); PRINT6ADDR(&UIP_IP_BUF->destipaddr); PRINTF(" from "); PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINTF("\n"); return; } /---------------------------------------------------------------------------/ /**
PRINTF("Received RA from "); PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINTF(" to "); PRINT6ADDR(&UIP_IP_BUF->destipaddr); PRINTF("\n"); UIP_STAT(++uip_stat.nd6.recv);
if ((nvm_data.mode & CETIC_MODE_WAIT_RA_MASK) == 0 ) { goto discard; }
if((UIP_IP_BUF->ttl != UIP_ND6_HOP_LIMIT) || (!uip_is_addr_linklocal(&UIP_IP_BUF->srcipaddr)) || (UIP_ICMP_BUF->icode != 0)) { PRINTF("RA received is bad"); goto discard; }
if(UIP_ND6_RA_BUF->cur_ttl != 0) { uip_ds6_if.cur_hop_limit = UIP_ND6_RA_BUF->cur_ttl; PRINTF("uip_ds6_if.cur_hop_limit %u\n", uip_ds6_if.cur_hop_limit); }
if(UIP_ND6_RA_BUF->reachable_time != 0) { if(uip_ds6_if.base_reachable_time != uip_ntohl(UIP_ND6_RA_BUF->reachable_time)) { uip_ds6_if.base_reachable_time = uip_ntohl(UIP_ND6_RA_BUF->reachable_time); uip_ds6_if.reachable_time = uip_ds6_compute_reachable_time(); } } if(UIP_ND6_RA_BUF->retrans_timer != 0) { uip_ds6_if.retrans_timer = uip_ntohl(UIP_ND6_RA_BUF->retrans_timer); }
/ Options processing / nd6_opt_offset = UIP_ND6_RA_LEN; while(uip_l3_icmp_hdr_len + nd6_opt_offset < uip_len) { if(UIP_ND6_OPT_HDR_BUF->len == 0) { PRINTF("RA received is bad"); goto discard; } switch (UIP_ND6_OPT_HDR_BUF->type) { case UIP_ND6_OPT_SLLAO: PRINTF("Processing SLLAO option in RA\n"); nd6_opt_llao = (uint8_t ) UIP_ND6_OPT_HDR_BUF; nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr); if(!extract_lladdr_from_llao_aligned(&lladdr_aligned)) { / failed to extract llao - discard packet / goto discard; } if(nbr == NULL) { nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned, 1, NBR_STALE, NBR_TABLE_REASON_IPV6_ND, NULL); } else { const uip_lladdr_t lladdr = uip_ds6_nbr_get_ll(nbr); if(lladdr == NULL) { goto discard; } if(nbr->state == NBR_INCOMPLETE) { nbr->state = NBR_STALE; } if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], lladdr, UIP_LLADDR_LEN) != 0) { / change of link layer address / if(uip_ds6_nbr_update_lladdr(&nbr, &lladdr_aligned) == 0) { / failed to update the lladdr / goto discard; } nbr->state = NBR_STALE; } nbr->isrouter = 1; } break; case UIP_ND6_OPT_MTU: PRINTF("Processing MTU option in RA\n"); uip_ds6_if.link_mtu = uip_ntohl(((uip_nd6_opt_mtu ) UIP_ND6_OPT_HDR_BUF)->mtu); break; case UIP_ND6_OPT_PREFIX_INFO: PRINTF("Processing PREFIX option in RA\n"); nd6_opt_prefix_info = (uip_nd6_opt_prefix_info ) UIP_ND6_OPT_HDR_BUF; if((uip_ntohl(nd6_opt_prefix_info->validlt) >= uip_ntohl(nd6_opt_prefix_info->preferredlt)) && (!uip_is_addr_linklocal(&nd6_opt_prefix_info->prefix))) { / on-link flag related processing /
if(nd6_opt_prefix_info->flagsreserved1 & UIP_ND6_RA_FLAG_ONLINK) {
prefix =
uip_ds6_prefix_lookup(&nd6_opt_prefix_info->prefix,
nd6_opt_prefix_info->preflen);
if(prefix == NULL) {
if(nd6_opt_prefix_info->validlt != 0) {
if(nd6_opt_prefix_info->validlt != UIP_ND6_INFINITE_LIFETIME) {
prefix = uip_ds6_prefix_add(&nd6_opt_prefix_info->prefix,
nd6_opt_prefix_info->preflen,
uip_ntohl(nd6_opt_prefix_info->
validlt));
} else {
prefix = uip_ds6_prefix_add(&nd6_opt_prefix_info->prefix,
nd6_opt_prefix_info->preflen, 0);
}
}
} else {
switch (nd6_opt_prefix_info->validlt) {
case 0:
uip_ds6_prefix_rm(prefix);
break;
case UIP_ND6_INFINITE_LIFETIME:
prefix->isinfinite = 1;
break;
default:
PRINTF("Updating timer of prefix ");
PRINT6ADDR(&prefix->ipaddr);
PRINTF(" new value %lu\n", uip_ntohl(nd6_opt_prefix_info->validlt));
stimer_set(&prefix->vlifetime,
uip_ntohl(nd6_opt_prefix_info->validlt));
prefix->isinfinite = 0;
break;
}
}
}
/* End of on-link flag related processing */
/* autonomous flag related processing */
if((nd6_opt_prefix_info->flagsreserved1 & UIP_ND6_RA_FLAG_AUTONOMOUS)
&& (nd6_opt_prefix_info->validlt != 0)
&& (nd6_opt_prefix_info->preflen == UIP_DEFAULT_PREFIX_LEN)) {
uip_ipaddr_copy(&ipaddr, &nd6_opt_prefix_info->prefix);
uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr);
addr = uip_ds6_addr_lookup(&ipaddr);
if((addr != NULL) && (addr->type == ADDR_AUTOCONF)) {
if(nd6_opt_prefix_info->validlt != UIP_ND6_INFINITE_LIFETIME) {
/* The processing below is defined in RFC4862 section 5.5.3 e */
if((uip_ntohl(nd6_opt_prefix_info->validlt) > 2 * 60 * 60) ||
(uip_ntohl(nd6_opt_prefix_info->validlt) >
stimer_remaining(&addr->vlifetime))) {
PRINTF("Updating timer of address ");
PRINT6ADDR(&addr->ipaddr);
PRINTF(" new value %lu\n",
uip_ntohl(nd6_opt_prefix_info->validlt));
stimer_set(&addr->vlifetime,
uip_ntohl(nd6_opt_prefix_info->validlt));
} else {
stimer_set(&addr->vlifetime, 2 * 60 * 60);
PRINTF("Updating timer of address ");
PRINT6ADDR(&addr->ipaddr);
PRINTF(" new value %lu\n", (unsigned long)(2 * 60 * 60));
}
addr->isinfinite = 0;
} else {
addr->isinfinite = 1;
}
} else {
if(uip_ntohl(nd6_opt_prefix_info->validlt) ==
UIP_ND6_INFINITE_LIFETIME) {
uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF);
} else {
uip_ds6_addr_add(&ipaddr, uip_ntohl(nd6_opt_prefix_info->validlt),
ADDR_AUTOCONF);
}
}
cetic_6lbr_set_prefix(&nd6_opt_prefix_info->prefix, 64, &ipaddr);
}
/* End of autonomous flag related processing */
}
break;
// bridge handling RIO to update routes
case UIP_ND6_OPT_ROUTE_INFO:
PRINTF("RIO option in RA\n");
uip_nd6_opt_route_info *rio = (uip_nd6_opt_route_info *) UIP_ND6_OPT_ROUTE_BUF;
uip_ds6_route_info_callback(rio, &UIP_IP_BUF->srcipaddr);
break;
case UIP_ND6_OPT_RDNSS:
PRINTF("Processing RDNSS option\n");
uint8_t naddr = (UIP_ND6_OPT_RDNSS_BUF->len - 1) / 2;
uip_ipaddr_t *ip = (uip_ipaddr_t *)(&UIP_ND6_OPT_RDNSS_BUF->ip);
PRINTF("got %d nameservers\n", naddr);
while(naddr-- > 0) {
PRINTF(" nameserver: ");
PRINT6ADDR(ip);
PRINTF(" lifetime: %lx\n", uip_ntohl(UIP_ND6_OPT_RDNSS_BUF->lifetime));
uip_nameserver_update(ip, uip_ntohl(UIP_ND6_OPT_RDNSS_BUF->lifetime));
ip++;
}
break;
default:
PRINTF("ND option not supported in RA\n");
break;
}
nd6_opt_offset += (UIP_ND6_OPT_HDR_BUF->len << 3);
}
defrt = uip_ds6_defrt_lookup(&UIP_IP_BUF->srcipaddr); if(UIP_ND6_RA_BUF->router_lifetime != 0) { if(nbr != NULL) { nbr->isrouter = 1; } if(defrt == NULL) { uip_ds6_defrt_add(&UIP_IP_BUF->srcipaddr, (unsigned long)(uip_ntohs(UIP_ND6_RA_BUF->router_lifetime))); } else { stimer_set(&(defrt->lifetime), (unsigned long)(uip_ntohs(UIP_ND6_RA_BUF->router_lifetime))); } } else { if(defrt != NULL) { uip_ds6_defrt_rm(defrt); } }
/* If the nbr just became reachable (e.g. it was in NBR_INCOMPLETE state
discard: uip_clear_buf(); return; }
/------------------------------------------------------------------/ / ICMPv6 input handlers /
UIP_ICMP6_HANDLER(ns_input_handler, ICMP6_NS, UIP_ICMP6_HANDLER_CODE_ANY, ns_input);
UIP_ICMP6_HANDLER(na_input_handler, ICMP6_NA, UIP_ICMP6_HANDLER_CODE_ANY, na_input);
UIP_ICMP6_HANDLER(rs_input_handler, ICMP6_RS, UIP_ICMP6_HANDLER_CODE_ANY, rs_input);
UIP_ICMP6_HANDLER(ra_input_handler, ICMP6_RA, UIP_ICMP6_HANDLER_CODE_ANY, ra_input);
/---------------------------------------------------------------------------/ void uip_nd6_init() {
/ Only handle NSs if we are prepared to send out NAs / uip_icmp6_register_input_handler(&ns_input_handler);
/*
/ Only accept RS if we are a router and happy to send out RAs / uip_icmp6_register_input_handler(&rs_input_handler);
/ Only process RAs if we are not a router / uip_icmp6_register_input_handler(&ra_input_handler);
} /---------------------------------------------------------------------------/ /* @} /
i think that has alignment issue is below structure define:
/*@{ Pointers to messages just after icmp header /
/ @} / / Pointer to ND option */
/ @} */
Thank you for the detailed feedback ! I made a more comprehensive fix, could you check if it works on your platform too ? It's available in this branch : https://github.com/cetic/6lbr/tree/fix-alignment
yes,update it ,but still remain some only when start the 6lbr service. starting webserver for 6lbr gateway [ 12.380000] usb 1-2: new high-speed USB device number 4 using nuc970-ehci [ 15.780000] Alignment trap: cetic_6lbr_smar (847) PC=0x00054f08 Instr=0xe78c000b Address=0x001e9022 FSR 0x801 [ 16.830000] Alignment trap: cetic_6lbr_smar (847) PC=0x00054f08 Instr=0xe78c000b Address=0x001e9022 FSR 0x801 [ 17.760000] usb 1-2: new high-speed USB device number 5 using nuc970-ehci [ 20.370000] Alignment trap: cetic_6lbr_smar (847) PC=0x00054f08 Instr=0xe78c000b Address=0x001e9022 FSR 0x801 [ 23.160000] Alignment trap: cetic_6lbr_smar (847) PC=0x00054f08 Instr=0xe78c000b Address=0x001e9022 FSR 0x801
And with your modifications you don't have them ? I may have missed one or two places.
yes,i am not found it,so not fixed it.because it is happened only when service starting and it is happen sometimes,attach the progam to debug is difficult. after update the last ,there are many NR node appeared. like below:
Program received signal SIGBUS, Bus error. 0x00083168 in uip_nd6_ra_output (dest=0x0) at ./../../core/net/ipv6/uip-nd6.c:940 940 UIP_ND6_OPT_ROUTE_BUF->rlifetime = uip_htonl(rtinfo->lifetime);
root@gateway:~# [ 564.320000] Alignment trap: cetic_6lbr_rout (3470) PC=0x0005b610 Instr=0xe58c5004 Address=0x001eab46 FSR 0x801 [ 575.940000] Alignment trap: cetic_6lbr_rout (3529) PC=0x0005b610 Instr=0xe58c5004 Address=0x001eab46 FSR 0x801 [ 584.250000] Alignment trap: cetic_6lbr_rout (3603) PC=0x0005b610 Instr=0xe58c5004 Address=0x001eab46 FSR 0x801 [ 592.670000] Alignment trap: cetic_6lbr_rout (3662) PC=0x0005b610 Instr=0xe58c5004 Address=0x001eab46 FSR 0x801 [ 600.300000] Alignment trap: cetic_6lbr_rout (3721) PC=0x0005b610 Instr=0xe58c5004 Address=0x001eab46 FSR 0x801 [ 611.860000] Alignment trap: cetic_6lbr_rout (3780) PC=0x0005b610 Instr=0xe58c5004 Address=0x001eab46 FSR 0x801 [ 619.570000] Alignment trap: cetic_6lbr_rout (3854) PC=0x0005b610 Instr=0xe58c5004 Address=0x001eab46 FSR 0x801 [ 627.090000] Alignment trap: cetic_6lbr_rout (3913) PC=0x0005b610 Instr=0xe58c5004 Address=0x001eab46 FSR 0x801 [ 634.610000] Alignment trap: cetic_6lbr_rout (3967) PC=0x0005b610 Instr=0xe58c5004 Address=0x001eab46 FSR 0x801 [ 642.430000] Alignment trap: cetic_6lbr_rout (4021) PC=0x0005b610 Instr=0xe58c5004 Address=0x001eab46 FSR 0x801 [ 650.550000] Alignment trap: cetic_6lbr_rout (4080) PC=0x0005b610 Instr=0xe58c5004 Address=0x001eab46 FSR 0x801 [ 658.580000] Alignment trap: cetic_6lbr_rout (4139) PC=0x0005b610 Instr=0xe58c5004 Address=0x001eab46 FSR 0x801 [ 666.400000] Alignment trap: cetic_6lbr_rout (4198) PC=0x0005b610 Instr=0xe58c5004 Address=0x001eab46 FSR 0x8