int mnlg_socket_recv_run(struct mnlg_socket *nlg, mnl_cb_t data_cb, void *data) { int err; do { err = mnl_socket_recvfrom(nlg->nl, nlg->buf, MNL_SOCKET_BUFFER_SIZE); if (err <= 0) break; err = mnl_cb_run2(nlg->buf, err, nlg->seq, nlg->portid, data_cb, data, mnlg_cb_array, ARRAY_SIZE(mnlg_cb_array)); } while (err > 0); return err; }
static void send_batch(struct mnl_socket *nl, struct mnl_nlmsg_batch *b, int portid) { int ret, fd = mnl_socket_get_fd(nl); size_t len = mnl_nlmsg_batch_size(b); char rcv_buf[MNL_SOCKET_BUFFER_SIZE]; ret = mnl_socket_sendto(nl, mnl_nlmsg_batch_head(b), len); if (ret == -1) { perror("mnl_socket_recvfrom"); exit(EXIT_FAILURE); } /* receive and digest all the acknowledgments from the kernel. */ struct timeval tv = { .tv_sec = 0, .tv_usec = 0 }; fd_set readfds; FD_ZERO(&readfds); FD_SET(fd, &readfds); ret = select(fd+1, &readfds, NULL, NULL, &tv); if (ret == -1) { perror("select"); exit(EXIT_FAILURE); } while (ret > 0 && FD_ISSET(fd, &readfds)) { ret = mnl_socket_recvfrom(nl, rcv_buf, sizeof(rcv_buf)); if (ret == -1) { perror("mnl_socket_recvfrom"); exit(EXIT_FAILURE); } ret = mnl_cb_run2(rcv_buf, ret, 0, portid, NULL, NULL, cb_ctl_array, MNL_ARRAY_SIZE(cb_ctl_array)); if (ret == -1) { perror("mnl_cb_run"); exit(EXIT_FAILURE); } ret = select(fd+1, &readfds, NULL, NULL, &tv); if (ret == -1) { perror("select"); exit(EXIT_FAILURE); } FD_ZERO(&readfds); FD_SET(fd, &readfds); } } int main(void) { struct mnl_socket *nl; char snd_buf[MNL_SOCKET_BUFFER_SIZE*2]; struct mnl_nlmsg_batch *b; int j; unsigned int seq, portid; uint16_t i; nl = mnl_socket_open(NETLINK_NETFILTER); if (nl == NULL) { perror("mnl_socket_open"); exit(EXIT_FAILURE); } if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) { perror("mnl_socket_bind"); exit(EXIT_FAILURE); } portid = mnl_socket_get_portid(nl); /* The buffer that we use to batch messages is MNL_SOCKET_BUFFER_SIZE * multiplied by 2 bytes long, but we limit the batch to half of it * since the last message that does not fit the batch goes over the * upper boundary, if you break this rule, expect memory corruptions. */ b = mnl_nlmsg_batch_start(snd_buf, MNL_SOCKET_BUFFER_SIZE); if (b == NULL) { perror("mnl_nlmsg_batch_start"); exit(EXIT_FAILURE); } seq = time(NULL); for (i=1024, j=0; i<65535; i++, j++) { put_msg(mnl_nlmsg_batch_current(b), i, seq+j); /* is there room for more messages in this batch? * if so, continue. */ if (mnl_nlmsg_batch_next(b)) continue; send_batch(nl, b, portid); /* this moves the last message that did not fit into the * batch to the head of it. */ mnl_nlmsg_batch_reset(b); } /* check if there is any message in the batch not sent yet. */ if (!mnl_nlmsg_batch_is_empty(b)) send_batch(nl, b, portid); mnl_nlmsg_batch_stop(b); mnl_socket_close(nl); return 0; }