1*4882a593Smuzhiyun #ifndef _LIBMNL_H_ 2*4882a593Smuzhiyun #define _LIBMNL_H_ 3*4882a593Smuzhiyun 4*4882a593Smuzhiyun #include <stdbool.h> 5*4882a593Smuzhiyun #include <stdio.h> 6*4882a593Smuzhiyun #include <stdint.h> 7*4882a593Smuzhiyun #include <unistd.h> 8*4882a593Smuzhiyun #include <sys/socket.h> /* for sa_family_t */ 9*4882a593Smuzhiyun #include <linux/netlink.h> 10*4882a593Smuzhiyun 11*4882a593Smuzhiyun #ifdef __cplusplus 12*4882a593Smuzhiyun extern "C" { 13*4882a593Smuzhiyun #endif 14*4882a593Smuzhiyun 15*4882a593Smuzhiyun /* 16*4882a593Smuzhiyun * Netlink socket API 17*4882a593Smuzhiyun */ 18*4882a593Smuzhiyun 19*4882a593Smuzhiyun #define MNL_SOCKET_AUTOPID 0 20*4882a593Smuzhiyun #define MNL_SOCKET_BUFFER_SIZE (sysconf(_SC_PAGESIZE) < 8192L ? sysconf(_SC_PAGESIZE) : 8192L) 21*4882a593Smuzhiyun #define MNL_SOCKET_DUMP_SIZE 32768 22*4882a593Smuzhiyun 23*4882a593Smuzhiyun struct mnl_socket; 24*4882a593Smuzhiyun 25*4882a593Smuzhiyun extern struct mnl_socket *mnl_socket_open(int bus); 26*4882a593Smuzhiyun extern struct mnl_socket *mnl_socket_open2(int bus, int flags); 27*4882a593Smuzhiyun extern struct mnl_socket *mnl_socket_fdopen(int fd); 28*4882a593Smuzhiyun extern int mnl_socket_bind(struct mnl_socket *nl, unsigned int groups, pid_t pid); 29*4882a593Smuzhiyun extern int mnl_socket_close(struct mnl_socket *nl); 30*4882a593Smuzhiyun extern int mnl_socket_get_fd(const struct mnl_socket *nl); 31*4882a593Smuzhiyun extern unsigned int mnl_socket_get_portid(const struct mnl_socket *nl); 32*4882a593Smuzhiyun extern ssize_t mnl_socket_sendto(const struct mnl_socket *nl, const void *req, size_t siz); 33*4882a593Smuzhiyun extern ssize_t mnl_socket_recvfrom(const struct mnl_socket *nl, void *buf, size_t siz); 34*4882a593Smuzhiyun extern int mnl_socket_setsockopt(const struct mnl_socket *nl, int type, void *buf, socklen_t len); 35*4882a593Smuzhiyun extern int mnl_socket_getsockopt(const struct mnl_socket *nl, int type, void *buf, socklen_t *len); 36*4882a593Smuzhiyun 37*4882a593Smuzhiyun /* 38*4882a593Smuzhiyun * Netlink message API 39*4882a593Smuzhiyun */ 40*4882a593Smuzhiyun 41*4882a593Smuzhiyun #define MNL_ALIGNTO 4 42*4882a593Smuzhiyun #define MNL_ALIGN(len) (((len)+MNL_ALIGNTO-1) & ~(MNL_ALIGNTO-1)) 43*4882a593Smuzhiyun #define MNL_NLMSG_HDRLEN MNL_ALIGN(sizeof(struct nlmsghdr)) 44*4882a593Smuzhiyun 45*4882a593Smuzhiyun extern size_t mnl_nlmsg_size(size_t len); 46*4882a593Smuzhiyun extern size_t mnl_nlmsg_get_payload_len(const struct nlmsghdr *nlh); 47*4882a593Smuzhiyun 48*4882a593Smuzhiyun /* Netlink message header builder */ 49*4882a593Smuzhiyun extern struct nlmsghdr *mnl_nlmsg_put_header(void *buf); 50*4882a593Smuzhiyun extern void *mnl_nlmsg_put_extra_header(struct nlmsghdr *nlh, size_t size); 51*4882a593Smuzhiyun 52*4882a593Smuzhiyun /* Netlink message iterators */ 53*4882a593Smuzhiyun extern bool mnl_nlmsg_ok(const struct nlmsghdr *nlh, int len); 54*4882a593Smuzhiyun extern struct nlmsghdr *mnl_nlmsg_next(const struct nlmsghdr *nlh, int *len); 55*4882a593Smuzhiyun 56*4882a593Smuzhiyun /* Netlink sequence tracking */ 57*4882a593Smuzhiyun extern bool mnl_nlmsg_seq_ok(const struct nlmsghdr *nlh, unsigned int seq); 58*4882a593Smuzhiyun 59*4882a593Smuzhiyun /* Netlink portID checking */ 60*4882a593Smuzhiyun extern bool mnl_nlmsg_portid_ok(const struct nlmsghdr *nlh, unsigned int portid); 61*4882a593Smuzhiyun 62*4882a593Smuzhiyun /* Netlink message getters */ 63*4882a593Smuzhiyun extern void *mnl_nlmsg_get_payload(const struct nlmsghdr *nlh); 64*4882a593Smuzhiyun extern void *mnl_nlmsg_get_payload_offset(const struct nlmsghdr *nlh, size_t offset); 65*4882a593Smuzhiyun extern void *mnl_nlmsg_get_payload_tail(const struct nlmsghdr *nlh); 66*4882a593Smuzhiyun 67*4882a593Smuzhiyun /* Netlink message printer */ 68*4882a593Smuzhiyun extern void mnl_nlmsg_fprintf(FILE *fd, const void *data, size_t datalen, size_t extra_header_size); 69*4882a593Smuzhiyun 70*4882a593Smuzhiyun /* Message batch helpers */ 71*4882a593Smuzhiyun struct mnl_nlmsg_batch; 72*4882a593Smuzhiyun extern struct mnl_nlmsg_batch *mnl_nlmsg_batch_start(void *buf, size_t bufsiz); 73*4882a593Smuzhiyun extern bool mnl_nlmsg_batch_next(struct mnl_nlmsg_batch *b); 74*4882a593Smuzhiyun extern void mnl_nlmsg_batch_stop(struct mnl_nlmsg_batch *b); 75*4882a593Smuzhiyun extern size_t mnl_nlmsg_batch_size(struct mnl_nlmsg_batch *b); 76*4882a593Smuzhiyun extern void mnl_nlmsg_batch_reset(struct mnl_nlmsg_batch *b); 77*4882a593Smuzhiyun extern void *mnl_nlmsg_batch_head(struct mnl_nlmsg_batch *b); 78*4882a593Smuzhiyun extern void *mnl_nlmsg_batch_current(struct mnl_nlmsg_batch *b); 79*4882a593Smuzhiyun extern bool mnl_nlmsg_batch_is_empty(struct mnl_nlmsg_batch *b); 80*4882a593Smuzhiyun 81*4882a593Smuzhiyun /* 82*4882a593Smuzhiyun * Netlink attributes API 83*4882a593Smuzhiyun */ 84*4882a593Smuzhiyun #define MNL_ATTR_HDRLEN MNL_ALIGN(sizeof(struct nlattr)) 85*4882a593Smuzhiyun 86*4882a593Smuzhiyun /* TLV attribute getters */ 87*4882a593Smuzhiyun extern uint16_t mnl_attr_get_type(const struct nlattr *attr); 88*4882a593Smuzhiyun extern uint16_t mnl_attr_get_len(const struct nlattr *attr); 89*4882a593Smuzhiyun extern uint16_t mnl_attr_get_payload_len(const struct nlattr *attr); 90*4882a593Smuzhiyun extern void *mnl_attr_get_payload(const struct nlattr *attr); 91*4882a593Smuzhiyun extern uint8_t mnl_attr_get_u8(const struct nlattr *attr); 92*4882a593Smuzhiyun extern uint16_t mnl_attr_get_u16(const struct nlattr *attr); 93*4882a593Smuzhiyun extern uint32_t mnl_attr_get_u32(const struct nlattr *attr); 94*4882a593Smuzhiyun extern uint64_t mnl_attr_get_u64(const struct nlattr *attr); 95*4882a593Smuzhiyun extern const char *mnl_attr_get_str(const struct nlattr *attr); 96*4882a593Smuzhiyun 97*4882a593Smuzhiyun /* TLV attribute putters */ 98*4882a593Smuzhiyun extern void mnl_attr_put(struct nlmsghdr *nlh, uint16_t type, size_t len, const void *data); 99*4882a593Smuzhiyun extern void mnl_attr_put_u8(struct nlmsghdr *nlh, uint16_t type, uint8_t data); 100*4882a593Smuzhiyun extern void mnl_attr_put_u16(struct nlmsghdr *nlh, uint16_t type, uint16_t data); 101*4882a593Smuzhiyun extern void mnl_attr_put_u32(struct nlmsghdr *nlh, uint16_t type, uint32_t data); 102*4882a593Smuzhiyun extern void mnl_attr_put_u64(struct nlmsghdr *nlh, uint16_t type, uint64_t data); 103*4882a593Smuzhiyun extern void mnl_attr_put_str(struct nlmsghdr *nlh, uint16_t type, const char *data); 104*4882a593Smuzhiyun extern void mnl_attr_put_strz(struct nlmsghdr *nlh, uint16_t type, const char *data); 105*4882a593Smuzhiyun 106*4882a593Smuzhiyun /* TLV attribute putters with buffer boundary checkings */ 107*4882a593Smuzhiyun extern bool mnl_attr_put_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, size_t len, const void *data); 108*4882a593Smuzhiyun extern bool mnl_attr_put_u8_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, uint8_t data); 109*4882a593Smuzhiyun extern bool mnl_attr_put_u16_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, uint16_t data); 110*4882a593Smuzhiyun extern bool mnl_attr_put_u32_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, uint32_t data); 111*4882a593Smuzhiyun extern bool mnl_attr_put_u64_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, uint64_t data); 112*4882a593Smuzhiyun extern bool mnl_attr_put_str_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, const char *data); 113*4882a593Smuzhiyun extern bool mnl_attr_put_strz_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, const char *data); 114*4882a593Smuzhiyun 115*4882a593Smuzhiyun /* TLV attribute nesting */ 116*4882a593Smuzhiyun extern struct nlattr *mnl_attr_nest_start(struct nlmsghdr *nlh, uint16_t type); 117*4882a593Smuzhiyun extern struct nlattr *mnl_attr_nest_start_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type); 118*4882a593Smuzhiyun extern void mnl_attr_nest_end(struct nlmsghdr *nlh, struct nlattr *start); 119*4882a593Smuzhiyun extern void mnl_attr_nest_cancel(struct nlmsghdr *nlh, struct nlattr *start); 120*4882a593Smuzhiyun 121*4882a593Smuzhiyun /* TLV validation */ 122*4882a593Smuzhiyun extern int mnl_attr_type_valid(const struct nlattr *attr, uint16_t maxtype); 123*4882a593Smuzhiyun 124*4882a593Smuzhiyun enum mnl_attr_data_type { 125*4882a593Smuzhiyun MNL_TYPE_UNSPEC, 126*4882a593Smuzhiyun MNL_TYPE_U8, 127*4882a593Smuzhiyun MNL_TYPE_U16, 128*4882a593Smuzhiyun MNL_TYPE_U32, 129*4882a593Smuzhiyun MNL_TYPE_U64, 130*4882a593Smuzhiyun MNL_TYPE_STRING, 131*4882a593Smuzhiyun MNL_TYPE_FLAG, 132*4882a593Smuzhiyun MNL_TYPE_MSECS, 133*4882a593Smuzhiyun MNL_TYPE_NESTED, 134*4882a593Smuzhiyun MNL_TYPE_NESTED_COMPAT, 135*4882a593Smuzhiyun MNL_TYPE_NUL_STRING, 136*4882a593Smuzhiyun MNL_TYPE_BINARY, 137*4882a593Smuzhiyun MNL_TYPE_MAX, 138*4882a593Smuzhiyun }; 139*4882a593Smuzhiyun 140*4882a593Smuzhiyun extern int mnl_attr_validate(const struct nlattr *attr, enum mnl_attr_data_type type); 141*4882a593Smuzhiyun extern int mnl_attr_validate2(const struct nlattr *attr, enum mnl_attr_data_type type, size_t len); 142*4882a593Smuzhiyun 143*4882a593Smuzhiyun /* TLV iterators */ 144*4882a593Smuzhiyun extern bool mnl_attr_ok(const struct nlattr *attr, int len); 145*4882a593Smuzhiyun extern struct nlattr *mnl_attr_next(const struct nlattr *attr); 146*4882a593Smuzhiyun 147*4882a593Smuzhiyun #define mnl_attr_for_each(attr, nlh, offset) \ 148*4882a593Smuzhiyun for ((attr) = mnl_nlmsg_get_payload_offset((nlh), (offset)); \ 149*4882a593Smuzhiyun mnl_attr_ok((attr), (char *)mnl_nlmsg_get_payload_tail(nlh) - (char *)(attr)); \ 150*4882a593Smuzhiyun (attr) = mnl_attr_next(attr)) 151*4882a593Smuzhiyun 152*4882a593Smuzhiyun #define mnl_attr_for_each_nested(attr, nest) \ 153*4882a593Smuzhiyun for ((attr) = mnl_attr_get_payload(nest); \ 154*4882a593Smuzhiyun mnl_attr_ok((attr), (char *)mnl_attr_get_payload(nest) + mnl_attr_get_payload_len(nest) - (char *)(attr)); \ 155*4882a593Smuzhiyun (attr) = mnl_attr_next(attr)) 156*4882a593Smuzhiyun 157*4882a593Smuzhiyun #define mnl_attr_for_each_payload(payload, payload_size) \ 158*4882a593Smuzhiyun for ((attr) = (payload); \ 159*4882a593Smuzhiyun mnl_attr_ok((attr), (char *)(payload) + payload_size - (char *)(attr)); \ 160*4882a593Smuzhiyun (attr) = mnl_attr_next(attr)) 161*4882a593Smuzhiyun 162*4882a593Smuzhiyun /* TLV callback-based attribute parsers */ 163*4882a593Smuzhiyun typedef int (*mnl_attr_cb_t)(const struct nlattr *attr, void *data); 164*4882a593Smuzhiyun 165*4882a593Smuzhiyun extern int mnl_attr_parse(const struct nlmsghdr *nlh, unsigned int offset, mnl_attr_cb_t cb, void *data); 166*4882a593Smuzhiyun extern int mnl_attr_parse_nested(const struct nlattr *attr, mnl_attr_cb_t cb, void *data); 167*4882a593Smuzhiyun extern int mnl_attr_parse_payload(const void *payload, size_t payload_len, mnl_attr_cb_t cb, void *data); 168*4882a593Smuzhiyun 169*4882a593Smuzhiyun /* 170*4882a593Smuzhiyun * callback API 171*4882a593Smuzhiyun */ 172*4882a593Smuzhiyun #define MNL_CB_ERROR -1 173*4882a593Smuzhiyun #define MNL_CB_STOP 0 174*4882a593Smuzhiyun #define MNL_CB_OK 1 175*4882a593Smuzhiyun 176*4882a593Smuzhiyun typedef int (*mnl_cb_t)(const struct nlmsghdr *nlh, void *data); 177*4882a593Smuzhiyun 178*4882a593Smuzhiyun extern int mnl_cb_run(const void *buf, size_t numbytes, unsigned int seq, 179*4882a593Smuzhiyun unsigned int portid, mnl_cb_t cb_data, void *data); 180*4882a593Smuzhiyun 181*4882a593Smuzhiyun extern int mnl_cb_run2(const void *buf, size_t numbytes, unsigned int seq, 182*4882a593Smuzhiyun unsigned int portid, mnl_cb_t cb_data, void *data, 183*4882a593Smuzhiyun const mnl_cb_t *cb_ctl_array, 184*4882a593Smuzhiyun unsigned int cb_ctl_array_len); 185*4882a593Smuzhiyun 186*4882a593Smuzhiyun /* 187*4882a593Smuzhiyun * other declarations 188*4882a593Smuzhiyun */ 189*4882a593Smuzhiyun 190*4882a593Smuzhiyun #ifndef SOL_NETLINK 191*4882a593Smuzhiyun #define SOL_NETLINK 270 192*4882a593Smuzhiyun #endif 193*4882a593Smuzhiyun 194*4882a593Smuzhiyun #ifndef MNL_ARRAY_SIZE 195*4882a593Smuzhiyun #define MNL_ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0])) 196*4882a593Smuzhiyun #endif 197*4882a593Smuzhiyun 198*4882a593Smuzhiyun #ifdef __cplusplus 199*4882a593Smuzhiyun } /* extern "C" */ 200*4882a593Smuzhiyun #endif 201*4882a593Smuzhiyun 202*4882a593Smuzhiyun #endif 203