#include "network_information.h"
-extern const sa_family_t nwi_af_list[2];
+#define NWI_IFSTATE_FLAGS_NOT_IN_LIST 0x0008
+#define NWI_IFSTATE_FLAGS_HAS_SIGNATURE 0x0010
+#define NWI_IFSTATE_FLAGS_NOT_IN_IFLIST 0x0020
-#define NWI_IFSTATE_FLAGS_NOT_IN_LIST 0x8
-#define NWI_IFSTATE_FLAGS_HAS_SIGNATURE 0x10
+/*
+ * NWI_IFSTATE_FLAGS_MASK
+ * - these are the bits that get preserved, all others are
+ * control (last item, diff)
+ */
+#define NWI_IFSTATE_FLAGS_MASK 0x00ff
+
+
+#define NWI_IFSTATE_FLAGS_DIFF_MASK 0x0f00
+#define NWI_IFSTATE_FLAGS_LAST_ITEM 0x1000
+
+typedef enum {
+ knwi_ifstate_difference_none = 0,
+ knwi_ifstate_difference_changed = 1,
+ knwi_ifstate_difference_removed = 2
+} nwi_ifstate_difference_t;
-#define NWI_PTR(type, name) \
- union { \
- type name; \
- uint64_t _ ## name ## _p; \
- }
typedef uint32_t Rank;
+typedef int32_t nwi_ifindex_t;
#pragma pack(4)
typedef struct _nwi_ifstate {
char ifname[IFNAMSIZ];
uint64_t flags;
- NWI_PTR(nwi_ifstate_t, af_alias);
+ nwi_ifindex_t af_alias_offset; /* relative index to alias */
Rank rank;
sa_family_t af;
union {
struct in_addr iaddr;
struct in6_addr iaddr6;
};
- NWI_PTR(const char *, diff_str);
uint64_t if_generation_count;
uint32_t reach_flags;
union {
} nwi_ifstate;
#pragma pack()
-/*
- * nwi_state
- *
- *+---------------------------------------------+
- *| generation_count |
- *| |
- *----------------------------------------------+
- *| size |
- *| |
- *|---------------------------------------------+
- *| ipv4_count |
- *| |
- *|---------------------------------------------+
- *| ipv6_count |
- *| |
- *|---------------------------------------------+
- *| ipv6_start |-------+
- *| | |
- *|---------------------------------------------+ |ipv6_start stores the index of the start of the v6 list.
- *| ref (reference count) | |
- *| | |
- *|---------------------------------------------+ |
- *| svr (TRUE if copied from server) | |
- *| | |
- *|---------------------------------------------+ |
- *| reach_flags_v4 | |
- *| | |
- *|---------------------------------------------+ |
- *| reach_flags_v6 | |
- *| | |
- *|---------------------------------------------+ |
- *| IPv4 nwi_ifstates | |
- *| |<------|-------+
- *| ... | | |
- *|---------------------------------------------+ | |
- *| Sentinel nwi_ifstates | | |
- *| flags =NWI_IFSTATE_FLAGS_RANK_NEVER) | | | af_alias points to the same ifstate in the
- *| | | | opposite (v4 -> v6 and vice versa) af list.
- *|---------------------------------------------+ | |
- *| IPv6 nwi_ifstates |<------+ |
- *| |<--------------+
- *| ... |
- *|---------------------------------------------+
- *| Sentinel nwi_ifstates |
- *| flags =NWI_IFSTATE_FLAGS_RANK_NEVER) |
- *| |
- *|---------------------------------------------+
- *
- */
+#define NWI_STATE_VERSION ((uint32_t)0x20150214)
+
#pragma pack(4)
typedef struct _nwi_state {
- uint64_t generation_count;
- uint32_t size;
- uint32_t ipv4_count;
- uint32_t ipv6_count;
- uint32_t ipv6_start;
- uint32_t ref;
- _Bool svr;
+ uint32_t version; /* NWI_STATE_VERSION */
+ nwi_ifindex_t max_if_count; /* available slots per protocol */
+ nwi_ifindex_t ipv4_count; /* # of v4 ifstates in use */
+ nwi_ifindex_t ipv6_count; /* # of v6 ifstates in use */
+ nwi_ifindex_t if_list_count; /* # of if_list[] slots in use */
+ uint32_t ref; /* reference count */
uint32_t reach_flags_v4;
uint32_t reach_flags_v6;
- nwi_ifstate nwi_ifstates[0];
+ uint64_t generation_count;
+ nwi_ifstate ifstate_list[1];/* (max_if_count * 2) ifstates */
+/* nwi_ifindex_t if_list[0]; max_if_count indices */
} nwi_state;
#pragma pack()
+static __inline__ int
+nwi_other_af(int af)
+{
+ return ((af == AF_INET) ? (AF_INET6) : (AF_INET));
+}
+
+static __inline__ size_t
+nwi_state_compute_size(unsigned int max_if_count)
+{
+ size_t size;
+
+ size = offsetof(nwi_state, ifstate_list[max_if_count * 2])
+ + sizeof(nwi_ifindex_t) * max_if_count;
+ return (size);
+}
+
+static __inline__ size_t
+nwi_state_size(nwi_state_t state)
+{
+ return (nwi_state_compute_size(state->max_if_count));
+}
+
+static __inline__ nwi_ifstate_t
+nwi_state_ifstate_list(nwi_state_t state, int af)
+{
+ if (af == AF_INET) {
+ return (state->ifstate_list);
+ }
+ return (state->ifstate_list + state->max_if_count);
+}
+
+static __inline__ nwi_ifindex_t *
+nwi_state_if_list(nwi_state_t state)
+{
+ return ((nwi_ifindex_t *)&state->ifstate_list[state->max_if_count * 2]);
+}
+
static __inline__ int
uint32_cmp(uint32_t a, uint32_t b)
{
return (af == AF_INET)?state->ipv4_count:state->ipv6_count;
}
+static __inline__ nwi_ifstate_t
+nwi_ifstate_get_alias(nwi_ifstate_t ifstate, int af)
+{
+ if (ifstate->af == af) {
+ return (ifstate);
+ }
+ if (ifstate->af_alias_offset == 0) {
+ return (NULL);
+ }
+ return (ifstate + ifstate->af_alias_offset);
+}
+
/*
* The ifstate list is sorted in order of decreasing priority, with the
* highest priority element appearing at index zero.
nwi_ifstate_t
nwi_state_get_ifstate_with_index(nwi_state_t state, int af, int idx)
{
- nwi_ifstate_t nwi_ifstate = NULL;
int i_idx = idx;
- if (idx > nwi_state_get_ifstate_count(state, af)) {
- return (nwi_ifstate);
+ if (idx >= nwi_state_get_ifstate_count(state, af)) {
+ return (NULL);
}
if (af == AF_INET6) {
- i_idx = idx + state->ipv6_start;
+ i_idx = idx + state->max_if_count;
}
- return &state->nwi_ifstates[i_idx];
+ return &state->ifstate_list[i_idx];
}
/*
nwi_ifstate_t ifstate = NULL;
if (state == NULL) {
- return ifstate;
+ return NULL;
}
count = (af == AF_INET)
nwi_state_new(nwi_state_t old_state, int elems);
nwi_state_t
-nwi_state_copy_priv(nwi_state_t old_state);
+nwi_state_make_copy(nwi_state_t state);
+
+static __inline__ void
+nwi_state_free(nwi_state_t state)
+{
+ free(state);
+ return;
+}
+
+void
+nwi_state_finalize(nwi_state_t state);
nwi_ifstate_t
-nwi_insert_ifstate(nwi_state_t state, const char* ifname, int af,
- uint64_t flags, Rank rank,
- void * ifa, struct sockaddr * vpn_server_addr, uint32_t reach_flags);
+nwi_state_add_ifstate(nwi_state_t state, const char* ifname, int af,
+ uint64_t flags, Rank rank,
+ void * ifa, struct sockaddr * vpn_server_addr, uint32_t reach_flags);
void
nwi_ifstate_set_signature(nwi_ifstate_t ifstate, uint8_t * signature);
void
nwi_state_clear(nwi_state_t state, int af);
-void
-nwi_state_set_last(nwi_state_t state, int af);
-
nwi_state_t
nwi_state_diff(nwi_state_t old_state, nwi_state_t new_state);
const char *
nwi_ifstate_get_diff_str(nwi_ifstate_t ifstate);
+nwi_ifstate_difference_t
+nwi_ifstate_get_difference(nwi_ifstate_t diff_ifstate);
+
void
_nwi_state_update_interface_generations(nwi_state_t old_state, nwi_state_t state, nwi_state_t changes);
void
_nwi_state_force_refresh();
+void
+_nwi_state_compute_sha1_hash(nwi_state_t state,
+ unsigned char hash[CC_SHA1_DIGEST_LENGTH]);
+
+
#endif