-/*l
+/*
* "Copyright (c) 2008 The Regents of the University of California.
* All rights reserved."
*
*/
uint8_t linklocal_prefix [] = {0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-uint8_t multicast_prefix [] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
struct in6_addr __my_address = {{{0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65}}};
}
uint8_t cmpPfx(ip6_addr_t a, uint8_t *pfx) {
- return (a[0] == pfx[0] &&
+ return (memcmp(a, pfx, 8) == 0);
+#if 0
+ (a[0] == pfx[0] &&
a[1] == pfx[1] &&
a[2] == pfx[2] &&
a[3] == pfx[3] &&
a[5] == pfx[5] &&
a[6] == pfx[6] &&
a[7] == pfx[7]);
+#endif
}
-int ipv6_addr_suffix_is_long(const ip6_addr_t addr) {
+static inline int ipv6_addr_suffix_is_long(const ip6_addr_t addr) {
return (!(addr[8] == 0 &&
addr[9] == 0 &&
addr[10] == 0 &&
addr[13] == 0));
}
+#if LIB6LOWPAN_FULL
/*
* return the length of the compressed fields in buf
*/
len += (buf - pkt->data);
return len;
}
+#endif
-int decompressShortAddress(uint8_t dispatch, uint8_t *s_addr, uint8_t *dest) {
+static inline int decompressShortAddress(uint8_t dispatch, uint8_t *s_addr, uint8_t *dest) {
if ((*s_addr & LOWPAN_IPHC_SHORT_MASK) == 0) {
// simplest case, just use the appropriate prefix.
if (dispatch == LOWPAN_HC_LOCAL_PATTERN)
}
// otherwise we either have an invalid compression, or else it's a
// multicast address
- ip_memcpy(dest, multicast_prefix, 8);
- ip_memclr(dest + 8, 8);
+ // ip_memcpy(dest, multicast_prefix, 8);
+ ip_memclr(dest, 16);
+ dest[0] = 0xff;
+ dest[1] = 0x02;
switch (*s_addr & LOWPAN_IPHC_SHORT_LONG_MASK) {
case LOWPAN_IPHC_HC1_MCAST:
dest[14] = (*s_addr) & ~LOWPAN_IPHC_SHORT_LONG_MASK;
return 0;
}
-int decompressAddress(uint8_t dispatch, uint16_t src, uint8_t addr_flags,
- uint8_t **buf, uint8_t *dest) {
+static inline int decompressAddress(uint8_t dispatch, uint16_t src, uint8_t addr_flags,
+ uint8_t **buf, uint8_t *dest) {
uint8_t *prefix;
uint16_t tmp;
int rc = 0;
return rc;
}
+void adjustPlen(struct ip6_hdr *ip, unpack_info_t *u_info) {
+ uint16_t adjust_amt = u_info->payload_offset;
+
+ switch (ip->nxt_hdr) {
+ case IANA_UDP:
+ adjust_amt -= sizeof(struct udp_hdr); break;
+ }
+ ip->plen = htons(ntohs(ip->plen) - adjust_amt);
+}
+
/*
* Unpacks all headers, including any compressed transport headers if
* there is a compression scheme defined for them.
// pointers to fields we may come back to fill in later
uint8_t *plen, *prot_len, *nxt_hdr;
- u_info->payload_offset = 0;
- u_info->rih = NULL;
- u_info->sh = NULL;
- u_info->transport_ptr = NULL;
+ ip_memclr((void *)u_info, sizeof(unpack_info_t));
// a buffer we can write addresses prefixes and suffexes into.
// now we don't need to check sizes until we get to next headers
uint8_t nhdr_len = 0;
struct ip6_ext *hdr;
u_info->nxt_hdr = nhdr;
- while (KNOWN_HEADER(nhdr)) {
+
+ // copy any IPv6 extension headers out of the packet.
+ // the rule is that the extension headers must fit in the first
+ // fragment so we can route on them after only one fragment.
+ while (EXTENSION_HEADER(nhdr)) {
hdr = (struct ip6_ext *)buf;
- u_info->nxt_hdr = nhdr;
+
switch (nhdr) {
- case IANA_UDP:
- nhdr = NXTHDR_UNKNOWN;
- nhdr_len = sizeof(struct udp_hdr);
- u_info->transport_ptr = dest;
+ case IPV6_HOP:
+ u_info->hdr_hop = (struct ip6_ext *)buf;
+ break;
+ case IPV6_ROUTING:
+ u_info->hdr_route = (struct ip6_route *)buf;
break;
- case NXTHDR_SOURCE:
- u_info->sh = (struct source_header *)buf;
- nhdr = hdr->nxt_hdr;
- nhdr_len = hdr->len;
- u_info->nxt_hdr = nhdr;
+ case IPV6_DEST:
+ u_info->hdr_dest = (struct ip6_ext *)buf;
break;
- case NXTHDR_INSTALL:
- // this is how to handle all ipv6 options headers: should we
- // use "default" here?
- u_info->rih = (struct rinstall_header *)buf;
- default:
- nhdr = hdr->nxt_hdr;
- nhdr_len = hdr->len;
- u_info->nxt_hdr = nhdr;
}
+ nhdr = hdr->nxt_hdr;
+ nhdr_len = hdr->len;
+ u_info->nxt_hdr = nhdr;
+
if (len < nhdr_len) return NULL;
ip_memcpy(dest, buf, nhdr_len);
dest += nhdr_len;
u_info->payload_offset += nhdr_len;
extra_header_length += nhdr_len;
}
+
+ u_info->transport_ptr = dest;
}
u_info->payload_start = buf;
* that was needed.
* @returns the bit flags indicating which length was used
*/
-uint8_t packAddress(uint8_t dispatch, uint8_t **buf, ip6_addr_t addr) {
+static uint8_t packAddress(uint8_t dispatch, uint8_t **buf, ip6_addr_t addr) {
if ((dispatch == LOWPAN_HC_CRP_PATTERN && globalPrefix &&
cmpPfx(addr, __my_address.s6_addr)) ||
}
nxt_hdr = hdr->nxt_hdr;
- if (hdr->nxt_hdr == IANA_UDP /* or other compressed values... */) {
+ if (hdr->nxt_hdr == IANA_UDP && /* or other compressed values... */
+ msg->headers != NULL) {
// we will add the HCNH encoding at the end of the header
*encoding |= LOWPAN_IPHC_NH_MASK;
} else {
/* } */
+
+#ifndef NO_LIB6LOWPAN_ASCII
+
+#define TO_CHAR(X) (((X) < 10) ? ('0' + (X)) : ('a' + ((X) - 10)))
#define CHAR_VAL(X) (((X) >= '0' && (X) <= '9') ? ((X) - '0') : \
(((X) >= 'A' && (X) <= 'F') ? ((X) - 'A' + 10) : ((X) - 'a' + 10)))
cur = 0;
}
p++;
- if (*p == '\0')
+ if (*p == '\0') {
+ dest->s6_addr16[block++] = hton16(cur);
return;
+ }
if (*(p - 1) == ':' && *p == ':') {
break;
}
if (*(p + 1) == ':' && *p == ':') break;
}
}
+
+
+
+int inet_ntop6(struct in6_addr *addr, char *buf, int cnt) {
+ uint16_t block;
+ char *end = buf + cnt;
+ int i, j, compressed = 0;
+
+ for (j = 0; j < 8; j++) {
+ if (buf > end - 7) return -1;
+
+ block = ntohs(addr->s6_addr16[j]);
+ for (i = 4; i <= 16; i+=4) {
+ if (block > (0xffff >> i) || (compressed == 2 && i == 16)) {
+ *buf++ = TO_CHAR((block >> (16 - i)) & 0xf);
+ }
+ }
+ if (addr->s6_addr16[j] == 0 && compressed == 0) {
+ *buf++ = ':';
+ compressed++;
+ }
+ if (addr->s6_addr16[j] != 0 && compressed == 1) compressed++;
+
+ if (j < 7 && compressed != 1) *buf++ = ':';
+ }
+ *buf++ = '\0';
+ return buf - (end - cnt);
+}
+
+#endif