/** * Create a netlink socket and connect to it kernel. * @arg handle netlink handle * @arg protocol desired netlink protocol * * Creates a netlink socket of the desired \c protocol and connects it * to the kernel. * * @note nl_handle::local::nl_groups may contain a multicast group mask. * @exception EADDRNOTAVAIL Invalid address length * @exception EPFNOSUPPORT Address format not supported */ int nl_connect(struct nl_handle *handle, int protocol) { int err; socklen_t addrlen; nl_init_handle(handle); if ((handle->h_fd = socket(AF_NETLINK, SOCK_RAW, protocol)) < 0) return nl_error(1, "socket(AF_NETLINK, ...) failed"); if ((err = nl_set_buffer_size(handle, 0, 0)) < 0) return err; err = bind(handle->h_fd, (struct sockaddr*) &handle->h_local, sizeof(handle->h_local)); if (err < 0) return nl_error(1, "bind() failed"); addrlen = sizeof(handle->h_local); err = getsockname(handle->h_fd, (struct sockaddr *) &handle->h_local, &addrlen); if (err < 0) return nl_error(1, "getsockname failed"); if (addrlen != sizeof(handle->h_local)) return nl_error(EADDRNOTAVAIL, "Invalid address length"); if (handle->h_local.nl_family != AF_NETLINK) return nl_error(EPFNOSUPPORT, "Address format not supported"); return 0; }
static inline int nl_socket_set_buffer_size(struct nl_sock *sk, int rxbuf, int txbuf) { return nl_set_buffer_size(sk, rxbuf, txbuf); }
/** * Setups generic netlink connection with the kernel module and retrieves assocaited family id * * @return 0 on success */ static int initialize_netlink_family(void) { struct nl_handle* hndl; struct nl_msg* msg = NULL; struct nl_msg *ans_msg = NULL; struct nlmsghdr *nl_hdr; struct genlmsghdr* genl_hdr; struct nlattr *nla; int ret_val = 0; hndl = nl_handle_alloc(); nl_set_buffer_size(hndl, 15000000, 15000000); //nl_handle_set_peer_pid(hndl, 0); //nl_set_passcred(hndl, 1); nl_disable_sequence_check(hndl); if ( (ret_val=nl_connect(hndl, NETLINK_GENERIC)) ) goto init_return; nl_set_buffer_size(hndl, 15000000, 15000000); if ( (ret_val=prepare_request_message(hndl, CTRL_CMD_GETFAMILY, GENL_ID_CTRL, &msg) ) != 0 ) { goto init_return; } ret_val = nla_put_string(msg, CTRL_ATTR_FAMILY_NAME, "DIRECTORCHNL"); if (ret_val != 0) goto init_return; if ( (ret_val = send_request_message(hndl, msg, 0) ) != 0 ) goto init_return; if ( (ret_val = read_message(hndl, &ans_msg) ) != 0 ) goto init_return; genl_hdr = nl_msg_genlhdr(ans_msg); if (genl_hdr == NULL || genl_hdr->cmd != CTRL_CMD_NEWFAMILY) { ret_val = -EBADMSG; goto init_return; } nla = nlmsg_find_attr(nlmsg_hdr(ans_msg), sizeof(struct genlmsghdr), CTRL_ATTR_FAMILY_ID); if (nla == NULL) { ret_val = -EBADMSG; goto init_return; } state.gnl_fid = nla_get_u16(nla); if (state.gnl_fid == 0) { ret_val = -EBADMSG; goto init_return; } state.handle = hndl; return 0; init_return: nlmsg_free(ans_msg); if ( state.handle == NULL ) { nl_close(hndl); nl_handle_destroy(hndl); } return -EINVAL; }