mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-05-19 14:28:13 +02:00
154 lines
4.6 KiB
C
154 lines
4.6 KiB
C
#pragma once
|
|
|
|
#include <c-list.h>
|
|
#include <c-rbtree.h>
|
|
#include <c-stdaux.h>
|
|
#include <errno.h>
|
|
#include <inttypes.h>
|
|
#include <netinet/if_ether.h>
|
|
#include <netinet/in.h>
|
|
#include <stdbool.h>
|
|
#include <stdlib.h>
|
|
#include "util/timer.h"
|
|
#include "n-acd.h"
|
|
|
|
typedef struct NAcdEventNode NAcdEventNode;
|
|
|
|
/* This augments the error-codes with internal ones that are never exposed. */
|
|
enum {
|
|
_N_ACD_INTERNAL = _N_ACD_E_N,
|
|
|
|
N_ACD_E_DROPPED,
|
|
};
|
|
|
|
enum {
|
|
N_ACD_PROBE_STATE_PROBING,
|
|
N_ACD_PROBE_STATE_CONFIGURING,
|
|
N_ACD_PROBE_STATE_ANNOUNCING,
|
|
N_ACD_PROBE_STATE_FAILED,
|
|
};
|
|
|
|
struct NAcdConfig {
|
|
int ifindex;
|
|
unsigned int transport;
|
|
uint8_t mac[ETH_ALEN];
|
|
size_t n_mac;
|
|
};
|
|
|
|
#define N_ACD_CONFIG_NULL(_x) { \
|
|
.transport = _N_ACD_TRANSPORT_N, \
|
|
}
|
|
|
|
struct NAcdProbeConfig {
|
|
struct in_addr ip;
|
|
uint64_t timeout_msecs;
|
|
};
|
|
|
|
#define N_ACD_PROBE_CONFIG_NULL(_x) { \
|
|
.timeout_msecs = N_ACD_TIMEOUT_RFC5227, \
|
|
}
|
|
|
|
struct NAcdEventNode {
|
|
CList acd_link;
|
|
CList probe_link;
|
|
NAcdEvent event;
|
|
uint8_t sender[ETH_ALEN];
|
|
bool is_public : 1;
|
|
};
|
|
|
|
#define N_ACD_EVENT_NODE_NULL(_x) { \
|
|
.acd_link = C_LIST_INIT((_x).acd_link), \
|
|
.probe_link = C_LIST_INIT((_x).probe_link), \
|
|
}
|
|
|
|
struct NAcd {
|
|
unsigned long n_refs;
|
|
unsigned int seed;
|
|
int fd_epoll;
|
|
int fd_socket;
|
|
CRBTree ip_tree;
|
|
CList event_list;
|
|
Timer timer;
|
|
|
|
/* BPF map */
|
|
int fd_bpf_map;
|
|
size_t n_bpf_map;
|
|
size_t max_bpf_map;
|
|
|
|
/* configuration */
|
|
int ifindex;
|
|
uint8_t mac[ETH_ALEN];
|
|
|
|
/* flags */
|
|
bool preempted : 1;
|
|
};
|
|
|
|
#define N_ACD_NULL(_x) { \
|
|
.n_refs = 1, \
|
|
.fd_epoll = -1, \
|
|
.fd_socket = -1, \
|
|
.ip_tree = C_RBTREE_INIT, \
|
|
.event_list = C_LIST_INIT((_x).event_list), \
|
|
.timer = TIMER_NULL((_x).timer), \
|
|
.fd_bpf_map = -1, \
|
|
}
|
|
|
|
struct NAcdProbe {
|
|
NAcd *acd;
|
|
CRBNode ip_node;
|
|
CList event_list;
|
|
Timeout timeout;
|
|
|
|
/* configuration */
|
|
struct in_addr ip;
|
|
uint64_t timeout_multiplier;
|
|
void *userdata;
|
|
|
|
/* state */
|
|
unsigned int state;
|
|
unsigned int n_iteration;
|
|
unsigned int defend;
|
|
uint64_t last_defend;
|
|
};
|
|
|
|
#define N_ACD_PROBE_NULL(_x) { \
|
|
.ip_node = C_RBNODE_INIT((_x).ip_node), \
|
|
.event_list = C_LIST_INIT((_x).event_list), \
|
|
.timeout = TIMEOUT_INIT((_x).timeout), \
|
|
.state = N_ACD_PROBE_STATE_PROBING, \
|
|
.defend = N_ACD_DEFEND_NEVER, \
|
|
}
|
|
|
|
/* events */
|
|
|
|
int n_acd_event_node_new(NAcdEventNode **nodep);
|
|
NAcdEventNode *n_acd_event_node_free(NAcdEventNode *node);
|
|
|
|
/* contexts */
|
|
|
|
void n_acd_remember(NAcd *acd, uint64_t now, bool success);
|
|
int n_acd_raise(NAcd *acd, NAcdEventNode **nodep, unsigned int event);
|
|
int n_acd_send(NAcd *acd, const struct in_addr *tpa, const struct in_addr *spa);
|
|
int n_acd_ensure_bpf_map_space(NAcd *acd);
|
|
|
|
/* probes */
|
|
|
|
int n_acd_probe_new(NAcdProbe **probep, NAcd *acd, NAcdProbeConfig *config);
|
|
int n_acd_probe_raise(NAcdProbe *probe, NAcdEventNode **nodep, unsigned int event);
|
|
int n_acd_probe_handle_timeout(NAcdProbe *probe);
|
|
int n_acd_probe_handle_packet(NAcdProbe *probe, struct ether_arp *packet, bool hard_conflict);
|
|
|
|
/* eBPF */
|
|
|
|
int n_acd_bpf_map_create(int *mapfdp, size_t max_elements);
|
|
int n_acd_bpf_map_add(int mapfd, struct in_addr *addr);
|
|
int n_acd_bpf_map_remove(int mapfd, struct in_addr *addr);
|
|
|
|
int n_acd_bpf_compile(int *progfdp, int mapfd, struct ether_addr *mac);
|
|
|
|
/* inline helpers */
|
|
|
|
static inline void n_acd_event_node_freep(NAcdEventNode **node) {
|
|
if (*node)
|
|
n_acd_event_node_free(*node);
|
|
}
|