#ifndef _NETWORK_H_ #define _NETWORK_H_ #include #include #define CONNTRACKD_PROTOCOL_VERSION 0 struct nf_conntrack; struct nethdr { uint8_t version:4, type:4; uint8_t flags; uint16_t len; uint32_t seq; }; #define NETHDR_SIZ nethdr_align(sizeof(struct nethdr)) enum nethdr_type { NET_T_STATE_NEW = 0, NET_T_STATE_UPD, NET_T_STATE_DEL, NET_T_STATE_MAX = NET_T_STATE_DEL, NET_T_CTL = 10, }; int nethdr_align(int len); int nethdr_size(int len); void nethdr_set(struct nethdr *net, int type); void nethdr_set_ack(struct nethdr *net); void nethdr_set_ctl(struct nethdr *net); #define NETHDR_DATA(x) \ (struct netattr *)(((char *)x) + NETHDR_SIZ) #define NETHDR_TAIL(x) \ (struct netattr *)(((char *)x) + x->len) struct nethdr_ack { uint8_t version:4, type:4; uint8_t flags; uint16_t len; uint32_t seq; uint32_t from; uint32_t to; }; #define NETHDR_ACK_SIZ nethdr_align(sizeof(struct nethdr_ack)) enum { NET_F_UNUSED = (1 << 0), NET_F_RESYNC = (1 << 1), NET_F_NACK = (1 << 2), NET_F_ACK = (1 << 3), NET_F_ALIVE = (1 << 4), NET_F_HELLO = (1 << 5), NET_F_HELLO_BACK= (1 << 6), }; enum { MSG_DATA, MSG_CTL, MSG_DROP, MSG_BAD, }; #define BUILD_NETMSG(ct, query) \ ({ \ char __net[4096]; \ struct nethdr *__hdr = (struct nethdr *) __net; \ memset(__hdr, 0, NETHDR_SIZ); \ nethdr_set(__hdr, query); \ build_payload(ct, __hdr); \ HDR_HOST2NETWORK(__hdr); \ __hdr; \ }) struct us_conntrack; struct mcast_sock; enum { SEQ_UNKNOWN, SEQ_UNSET, SEQ_IN_SYNC, SEQ_AFTER, SEQ_BEFORE, }; int mcast_track_seq(uint32_t seq, uint32_t *exp_seq); void mcast_track_update_seq(uint32_t seq); int mcast_track_is_seq_set(void); struct mcast_conf; int mcast_buffered_init(int mtu); void mcast_buffered_destroy(void); int mcast_buffered_send_netmsg(struct mcast_sock *m, const struct nethdr *net); ssize_t mcast_buffered_pending_netmsg(struct mcast_sock *m); #define IS_DATA(x) (x->type <= NET_T_STATE_MAX && \ (x->flags & ~(NET_F_HELLO | NET_F_HELLO_BACK)) == 0) #define IS_ACK(x) (x->type == NET_T_CTL && x->flags & NET_F_ACK) #define IS_NACK(x) (x->type == NET_T_CTL && x->flags & NET_F_NACK) #define IS_RESYNC(x) (x->type == NET_T_CTL && x->flags & NET_F_RESYNC) #define IS_ALIVE(x) (x->type == NET_T_CTL && x->flags & NET_F_ALIVE) #define IS_HELLO(x) (x->flags & NET_F_HELLO) #define IS_HELLO_BACK(x)(x->flags & NET_F_HELLO_BACK) #define HDR_NETWORK2HOST(x) \ ({ \ x->len = ntohs(x->len); \ x->seq = ntohl(x->seq); \ if (IS_ACK(x) || IS_NACK(x) || IS_RESYNC(x)) { \ struct nethdr_ack *__ack = (struct nethdr_ack *) x; \ __ack->from = ntohl(__ack->from); \ __ack->to = ntohl(__ack->to); \ } \ }) #define HDR_HOST2NETWORK(x) \ ({ \ if (IS_ACK(x) || IS_NACK(x) || IS_RESYNC(x)) { \ struct nethdr_ack *__ack = (struct nethdr_ack *) x; \ __ack->from = htonl(__ack->from); \ __ack->to = htonl(__ack->to); \ } \ x->len = htons(x->len); \ x->seq = htonl(x->seq); \ }) /* extracted from net/tcp.h */ /* * The next routines deal with comparing 32 bit unsigned ints * and worry about wraparound (automatic with unsigned arithmetic). */ static inline int before(uint32_t seq1, uint32_t seq2) { return (int32_t)(seq1-seq2) < 0; } #define after(seq2, seq1) before(seq1, seq2) /* is s2<=s1<=s3 ? */ static inline int between(uint32_t seq1, uint32_t seq2, uint32_t seq3) { return seq3 - seq2 >= seq1 - seq2; } #define PLD_NETWORK2HOST(x) \ ({ \ x->len = ntohs(x->len); \ x->query = ntohs(x->query); \ }) #define PLD_HOST2NETWORK(x) \ ({ \ x->len = htons(x->len); \ x->query = htons(x->query); \ }) struct netattr { uint16_t nta_len; uint16_t nta_attr; }; #define ATTR_NETWORK2HOST(x) \ ({ \ x->nta_len = ntohs(x->nta_len); \ x->nta_attr = ntohs(x->nta_attr); \ }) #define NTA_SIZE(len) NTA_ALIGN(sizeof(struct netattr)) + len #define NTA_DATA(x) \ (void *)(((char *)x) + NTA_ALIGN(sizeof(struct netattr))) #define NTA_NEXT(x, len) \ ( \ len -= NTA_ALIGN(x->nta_len), \ (struct netattr *)(((char *)x) + NTA_ALIGN(x->nta_len)) \ ) #define NTA_ALIGNTO 4 #define NTA_ALIGN(len) (((len) + NTA_ALIGNTO - 1) & ~(NTA_ALIGNTO - 1)) #define NTA_LENGTH(len) (NTA_ALIGN(sizeof(struct netattr)) + (len)) enum nta_attr { NTA_IPV4 = 0, /* struct nfct_attr_grp_ipv4 */ NTA_IPV6, /* struct nfct_attr_grp_ipv6 */ NTA_L4PROTO, /* uint8_t */ NTA_PORT, /* struct nfct_attr_grp_port */ NTA_STATE = 4, /* uint8_t */ NTA_STATUS, /* uint32_t */ NTA_TIMEOUT, /* uint32_t -- unused */ NTA_MARK, /* uint32_t */ NTA_MASTER_IPV4 = 8, /* struct nfct_attr_grp_ipv4 */ NTA_MASTER_IPV6, /* struct nfct_attr_grp_ipv6 */ NTA_MASTER_L4PROTO, /* uint8_t */ NTA_MASTER_PORT, /* struct nfct_attr_grp_port */ NTA_SNAT_IPV4 = 12, /* uint32_t */ NTA_DNAT_IPV4, /* uint32_t */ NTA_SPAT_PORT, /* uint16_t */ NTA_DPAT_PORT, /* uint16_t */ NTA_NAT_SEQ_ADJ = 16, /* struct nta_attr_natseqadj */ NTA_MAX }; struct nta_attr_natseqadj { uint32_t orig_seq_correction_pos; uint32_t orig_seq_offset_before; uint32_t orig_seq_offset_after; uint32_t repl_seq_correction_pos; uint32_t repl_seq_offset_before; uint32_t repl_seq_offset_after; }; void build_payload(const struct nf_conntrack *ct, struct nethdr *n); int parse_payload(struct nf_conntrack *ct, struct nethdr *n, size_t remain); #endif