aboutsummaryrefslogtreecommitdiff
path: root/lib/libnet/ipv6.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libnet/ipv6.c')
-rw-r--r--lib/libnet/ipv6.c72
1 files changed, 33 insertions, 39 deletions
diff --git a/lib/libnet/ipv6.c b/lib/libnet/ipv6.c
index 6c6fb54..6420004 100644
--- a/lib/libnet/ipv6.c
+++ b/lib/libnet/ipv6.c
@@ -116,15 +116,12 @@ ip6_addr_t *get_ipv6_address(void)
* @return 0 - IPv6 address is not in list
* 1 - IPv6 address is in list
*/
-static int8_t find_ip6addr(ip6_addr_t *ip)
+static int8_t find_ip6addr(ip6_addr_t ip)
{
struct ip6addr_list_entry *n = NULL;
- if (ip == NULL)
- return 0;
-
for (n = first_ip6; n != NULL ; n=n->next)
- if (ip6_cmp (&(n->addr), ip))
+ if (ip6_cmp(n->addr, ip))
return 1; /* IPv6 address is in our list*/
return 0; /* not one of our IPv6 addresses*/
@@ -149,7 +146,7 @@ int8_t handle_ipv6(int fd, uint8_t * ip6_packet, uint32_t packetsize)
ip6 = (struct ip6hdr *) ip6_packet;
/* Only handle packets which are for us */
- if (! find_ip6addr(&(ip6->dst)))
+ if (!find_ip6addr(ip6->dst))
return -1;
if (packetsize < sizeof(struct ip6hdr))
@@ -307,7 +304,7 @@ int8_t ip6addr_add(struct ip6addr_list_entry *new_address)
return 0;
/* Don't add the same address twice */
- if (find_ip6addr (&(new_address->addr)))
+ if (find_ip6addr(new_address->addr))
return 0;
/* If address is a unicast address, we also have to process packets
@@ -379,10 +376,9 @@ static void ipv6_init(int fd)
* @param ip6_addr ip_1
* @param ip6_addr ip_2
*/
-int8_t ip6_cmp(ip6_addr_t *ip_1, ip6_addr_t *ip_2)
+int8_t ip6_cmp(ip6_addr_t ip_1, ip6_addr_t ip_2)
{
- return ((int8_t) !memcmp( &(ip_1->addr[0]), &(ip_2->addr[0]),
- IPV6_ADDR_LENGTH ));
+ return !memcmp(ip_1.addr, ip_2.addr, IPV6_ADDR_LENGTH);
}
/**
@@ -434,34 +430,33 @@ static bool is_ip6addr_in_my_net(ip6_addr_t *ip)
* (e.g. UDP or ICMPv6)
*
* @param struct ip6hdr *ip6h - pointer to IPv6 header
- * @param unsigned short *packet - pointer to header of upper-layer
+ * @param unsigned char *packet - pointer to header of upper-layer
* protocol
- * @param int words - number of words (as in 2 bytes)
+ * @param int bytes - number of bytes
* starting from *packet
* @return checksum
*/
-static unsigned short ip6_checksum(struct ip6hdr *ip6h, unsigned short *packet,
- int words)
+static unsigned short ip6_checksum(struct ip6hdr *ip6h, unsigned char *packet,
+ int bytes)
{
- int i=0;
+ int i;
unsigned long checksum;
- struct ip6hdr pseudo_ip6h;
- unsigned short *pip6h;
-
- memcpy (&pseudo_ip6h, ip6h, sizeof(struct ip6hdr));
- pseudo_ip6h.hl = ip6h->nh;
- pseudo_ip6h.ver_tc_fl = 0;
- pseudo_ip6h.nh = 0;
- pip6h = (unsigned short *) &pseudo_ip6h;
-
- for (checksum = 0; words > 0; words--) {
- checksum += *packet++;
- i++;
- }
+ const int ip6size = sizeof(struct ip6hdr)/sizeof(unsigned short);
+ union {
+ struct ip6hdr ip6h;
+ unsigned short raw[ip6size];
+ } pseudo;
- for (i = 0; i < 20; i++) {
- checksum += *pip6h++;
- }
+ memcpy (&pseudo.ip6h, ip6h, sizeof(struct ip6hdr));
+ pseudo.ip6h.hl = ip6h->nh;
+ pseudo.ip6h.ver_tc_fl = 0;
+ pseudo.ip6h.nh = 0;
+
+ for (checksum = 0, i = 0; i < bytes; i += 2)
+ checksum += (packet[i] << 8) | packet[i + 1];
+
+ for (i = 0; i < ip6size; i++)
+ checksum += pseudo.raw[i];
checksum = (checksum >> 16) + (checksum & 0xffff);
checksum += (checksum >> 16);
@@ -503,12 +498,12 @@ int send_ipv6(int fd, void* buffer, int len)
if(len + sizeof(struct ethhdr) > ETH_MTU_SIZE)
return -1;
- if ( ip6_cmp (&ip6h->src, &null_ip6))
+ if ( ip6_cmp(ip6h->src, null_ip6))
memcpy (&(ip6h->src), get_ipv6_address(), IPV6_ADDR_LENGTH);
if (ip6h->nh == 17) {//UDP
- udph->uh_sum = ip6_checksum (ip6h, (unsigned short *) udph ,
- ip6h->pl >> 1);
+ udph->uh_sum = ip6_checksum (ip6h, (unsigned char *) udph,
+ ip6h->pl);
/* As per RFC 768, if the computed checksum is zero,
* it is transmitted as all ones (the equivalent in
* one's complement arithmetic).
@@ -517,9 +512,8 @@ int send_ipv6(int fd, void* buffer, int len)
udph->uh_sum = ~udph->uh_sum;
}
else if (ip6h->nh == 0x3a) //ICMPv6
- icmp6h->checksum = ip6_checksum (ip6h,
- (unsigned short *) icmp6h,
- ip6h->pl >> 1);
+ icmp6h->checksum = ip6_checksum (ip6h, (unsigned char *) icmp6h,
+ ip6h->pl);
if (ip6_is_multicast (&ip_dst)) {
/* If multicast, then create a proper multicast mac address */
@@ -527,11 +521,11 @@ int send_ipv6(int fd, void* buffer, int len)
} else if (!is_ip6addr_in_my_net(&ip_dst)) {
/* If server is not in same subnet, user MAC of the router */
struct router *gw;
- gw = ipv6_get_default_router(&ip6h->src);
+ gw = ipv6_get_default_router(ip6h->src);
mac_addr = gw ? gw->mac : null_mac;
} else {
/* Normal unicast, so use neighbor cache to look up MAC */
- struct neighbor *n = find_neighbor (&ip_dst);
+ struct neighbor *n = find_neighbor(ip_dst);
if (n) { /* Already cached ? */
if (memcmp(n->mac, null_mac, ETH_ALEN) != 0)
mac_addr = n->mac; /* found it */