/*
- * Copyright (c) 2009 Nicira Networks.
+ * Copyright (c) 2009, 2010 Nicira Networks.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <config.h>
#include "packets.h"
+#include <assert.h>
+#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
+#include "byte-order.h"
+#include "dynamic-string.h"
#include "ofpbuf.h"
+const struct in6_addr in6addr_exact = IN6ADDR_EXACT_INIT;
+
+/* Parses 's' as a 16-digit hexadecimal number representing a datapath ID. On
+ * success stores the dpid into '*dpidp' and returns true, on failure stores 0
+ * into '*dpidp' and returns false.
+ *
+ * Rejects an all-zeros dpid as invalid. */
bool
dpid_from_string(const char *s, uint64_t *dpidp)
{
- *dpidp = (strlen(s) == 12 && strspn(s, "0123456789abcdefABCDEF") == 12
- ? strtoll(s, NULL, 16)
+ *dpidp = (strlen(s) == 16 && strspn(s, "0123456789abcdefABCDEF") == 16
+ ? strtoull(s, NULL, 16)
: 0);
return *dpidp != 0;
}
memcpy(llc_snap->snap.snap_org, "\x00\x23\x20", 3);
llc_snap->snap.snap_type = htons(snap_type);
}
+
+/* Stores the string representation of the IPv6 address 'addr' into the
+ * character array 'addr_str', which must be at least INET6_ADDRSTRLEN
+ * bytes long. */
+void
+format_ipv6_addr(char *addr_str, const struct in6_addr *addr)
+{
+ inet_ntop(AF_INET6, addr, addr_str, INET6_ADDRSTRLEN);
+}
+
+void
+print_ipv6_addr(struct ds *string, const struct in6_addr *addr)
+{
+ char addr_str[INET6_ADDRSTRLEN];
+
+ format_ipv6_addr(addr_str, addr);
+ ds_put_format(string, "%s", addr_str);
+}
+
+struct in6_addr ipv6_addr_bitand(const struct in6_addr *a,
+ const struct in6_addr *b)
+{
+ int i;
+ struct in6_addr dst;
+
+#ifdef s6_addr32
+ for (i=0; i<4; i++) {
+ dst.s6_addr32[i] = a->s6_addr32[i] & b->s6_addr32[i];
+ }
+#else
+ for (i=0; i<16; i++) {
+ dst.s6_addr[i] = a->s6_addr[i] & b->s6_addr[i];
+ }
+#endif
+
+ return dst;
+}
+
+/* Returns an in6_addr consisting of 'mask' high-order 1-bits and 128-N
+ * low-order 0-bits. */
+struct in6_addr
+ipv6_create_mask(int mask)
+{
+ struct in6_addr netmask;
+ uint8_t *netmaskp = &netmask.s6_addr[0];
+
+ memset(&netmask, 0, sizeof netmask);
+ while (mask > 8) {
+ *netmaskp = 0xff;
+ netmaskp++;
+ mask -= 8;
+ }
+
+ if (mask) {
+ *netmaskp = 0xff << (8 - mask);
+ }
+
+ return netmask;
+}
+
+/* Given the IPv6 netmask 'netmask', returns the number of bits of the
+ * IPv6 address that it wildcards. 'netmask' must be a CIDR netmask (see
+ * ipv6_is_cidr()). */
+int
+ipv6_count_cidr_bits(const struct in6_addr *netmask)
+{
+ int i;
+ int count = 0;
+ const uint8_t *netmaskp = &netmask->s6_addr[0];
+
+ assert(ipv6_is_cidr(netmask));
+
+ for (i=0; i<16; i++) {
+ if (netmaskp[i] == 0xff) {
+ count += 8;
+ } else {
+ uint8_t nm;
+
+ for(nm = netmaskp[i]; nm; nm <<= 1) {
+ count++;
+ }
+ break;
+ }
+
+ }
+
+ return count;
+}
+
+
+/* Returns true if 'netmask' is a CIDR netmask, that is, if it consists of N
+ * high-order 1-bits and 128-N low-order 0-bits. */
+bool
+ipv6_is_cidr(const struct in6_addr *netmask)
+{
+ const uint8_t *netmaskp = &netmask->s6_addr[0];
+ int i;
+
+ for (i=0; i<16; i++) {
+ if (netmaskp[i] != 0xff) {
+ uint8_t x = ~netmaskp[i];
+ if (x & (x + 1)) {
+ return false;
+ }
+ while (++i < 16) {
+ if (netmaskp[i]) {
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+}