diff options
Diffstat (limited to 'libnl_2/genl/genl.c')
-rw-r--r-- | libnl_2/genl/genl.c | 302 |
1 files changed, 0 insertions, 302 deletions
diff --git a/libnl_2/genl/genl.c b/libnl_2/genl/genl.c deleted file mode 100644 index 1a39c6a..0000000 --- a/libnl_2/genl/genl.c +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* NOTICE: This is a clean room re-implementation of libnl */ - -#include <errno.h> -#include <unistd.h> -#include <stdio.h> -#include <sys/time.h> -#include <sys/socket.h> -#include <linux/netlink.h> -#include <netlink/genl/ctrl.h> -#include <netlink/genl/family.h> -#include "netlink-types.h" - -/* Get head of attribute data. */ -struct nlattr *genlmsg_attrdata(const struct genlmsghdr *gnlh, int hdrlen) -{ - return (struct nlattr *) \ - ((char *) gnlh + GENL_HDRLEN + NLMSG_ALIGN(hdrlen)); - -} - -/* Get length of attribute data. */ -int genlmsg_attrlen(const struct genlmsghdr *gnlh, int hdrlen) -{ - struct nlattr *nla; - struct nlmsghdr *nlh; - - nla = genlmsg_attrdata(gnlh, hdrlen); - nlh = (struct nlmsghdr *) ((char *) gnlh - NLMSG_HDRLEN); - return (char *) nlmsg_tail(nlh) - (char *) nla; -} - -/* Add generic netlink header to netlink message. */ -void *genlmsg_put(struct nl_msg *msg, uint32_t pid, uint32_t seq, int family, - int hdrlen, int flags, uint8_t cmd, uint8_t version) -{ - int new_size; - struct nlmsghdr *nlh; - struct timeval tv; - struct genlmsghdr *gmh; - - /* Make sure nl_msg has enough space */ - new_size = NLMSG_HDRLEN + GENL_HDRLEN + hdrlen; - if ((sizeof(struct nl_msg) + new_size) > msg->nm_size) - goto fail; - - /* Fill in netlink header */ - nlh = msg->nm_nlh; - nlh->nlmsg_len = new_size; - nlh->nlmsg_type = family; - nlh->nlmsg_pid = getpid(); - nlh->nlmsg_flags = flags | NLM_F_REQUEST | NLM_F_ACK; - - /* Get current time for sequence number */ - if (gettimeofday(&tv, NULL)) - nlh->nlmsg_seq = 1; - else - nlh->nlmsg_seq = (int) tv.tv_sec; - - /* Setup genlmsghdr in new message */ - gmh = (struct genlmsghdr *) ((char *)nlh + NLMSG_HDRLEN); - gmh->cmd = (__u8) cmd; - gmh->version = version; - - return gmh; -fail: - return NULL; - -} - -/* Socket has already been alloced to connect it to kernel? */ -int genl_connect(struct nl_sock *sk) -{ - return nl_connect(sk, NETLINK_GENERIC); - -} - -int genl_ctrl_alloc_cache(struct nl_sock *sock, struct nl_cache **result) -{ - int rc = -1; - int nl80211_genl_id = -1; - char sendbuf[sizeof(struct nlmsghdr)+sizeof(struct genlmsghdr)]; - struct nlmsghdr nlmhdr; - struct genlmsghdr gmhhdr; - struct iovec sendmsg_iov; - struct msghdr msg; - int num_char; - const int RECV_BUF_SIZE = getpagesize(); - char *recvbuf; - struct iovec recvmsg_iov; - int nl80211_flag = 0, nlm_f_multi = 0, nlmsg_done = 0; - struct nlmsghdr *nlh; - - /* REQUEST GENERIC NETLINK FAMILY ID */ - /* Message buffer */ - nlmhdr.nlmsg_len = sizeof(sendbuf); - nlmhdr.nlmsg_type = NETLINK_GENERIC; - nlmhdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP; - nlmhdr.nlmsg_seq = sock->s_seq_next; - nlmhdr.nlmsg_pid = sock->s_local.nl_pid; - - /* Generic netlink header */ - memset(&gmhhdr, 0, sizeof(gmhhdr)); - gmhhdr.cmd = CTRL_CMD_GETFAMILY; - gmhhdr.version = CTRL_ATTR_FAMILY_ID; - - /* Combine netlink and generic netlink headers */ - memcpy(&sendbuf[0], &nlmhdr, sizeof(nlmhdr)); - memcpy(&sendbuf[0]+sizeof(nlmhdr), &gmhhdr, sizeof(gmhhdr)); - - /* Create IO vector with Netlink message */ - sendmsg_iov.iov_base = &sendbuf; - sendmsg_iov.iov_len = sizeof(sendbuf); - - /* Socket message */ - msg.msg_name = (void *) &sock->s_peer; - msg.msg_namelen = sizeof(sock->s_peer); - msg.msg_iov = &sendmsg_iov; - msg.msg_iovlen = 1; /* Only sending one iov */ - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_flags = 0; - - /* Send message and verify sent */ - num_char = sendmsg(sock->s_fd, &msg, 0); - if (num_char == -1) - return -errno; - - /* RECEIVE GENL CMD RESPONSE */ - - /* Create receive iov buffer */ - recvbuf = (char *) malloc(RECV_BUF_SIZE); - - /* Attach to iov */ - recvmsg_iov.iov_base = recvbuf; - recvmsg_iov.iov_len = RECV_BUF_SIZE; - - msg.msg_iov = &recvmsg_iov; - msg.msg_iovlen = 1; - - /***************************************************************/ - /* Receive message. If multipart message, keep receiving until */ - /* message type is NLMSG_DONE */ - /***************************************************************/ - - do { - - int recvmsg_len, nlmsg_rem; - - /* Receive message */ - memset(recvbuf, 0, RECV_BUF_SIZE); - recvmsg_len = recvmsg(sock->s_fd, &msg, 0); - - /* Make sure receive successful */ - if (recvmsg_len < 0) { - rc = -errno; - goto error_recvbuf; - } - - /* Parse nlmsghdr */ - nlmsg_for_each_msg(nlh, (struct nlmsghdr *) recvbuf, \ - recvmsg_len, nlmsg_rem) { - struct nlattr *nla; - int nla_rem; - - /* Check type */ - switch (nlh->nlmsg_type) { - case NLMSG_DONE: - goto return_genl_id; - break; - case NLMSG_ERROR: - - /* Should check nlmsgerr struct received */ - fprintf(stderr, "Receive message error\n"); - goto error_recvbuf; - case NLMSG_OVERRUN: - fprintf(stderr, "Receive data partly lost\n"); - goto error_recvbuf; - case NLMSG_MIN_TYPE: - case NLMSG_NOOP: - break; - default: - break; - } - - - - /* Check flags */ - if (nlh->nlmsg_flags & NLM_F_MULTI) - nlm_f_multi = 1; - else - nlm_f_multi = 0; - - if (nlh->nlmsg_type & NLMSG_DONE) - nlmsg_done = 1; - else - nlmsg_done = 0; - - /* Iteratve over attributes */ - nla_for_each_attr(nla, - nlmsg_attrdata(nlh, GENL_HDRLEN), - nlmsg_attrlen(nlh, GENL_HDRLEN), - nla_rem){ - - /* If this family is nl80211 */ - if (nla->nla_type == CTRL_ATTR_FAMILY_NAME && - !strcmp((char *)nla_data(nla), - "nl80211")) - nl80211_flag = 1; - - /* Save the family id */ - else if (nl80211_flag && - nla->nla_type == CTRL_ATTR_FAMILY_ID) { - nl80211_genl_id = - *((int *)nla_data(nla)); - nl80211_flag = 0; - } - - } - - } - - } while (nlm_f_multi && !nlmsg_done); - -return_genl_id: - /* Return family id as cache pointer */ - *result = (struct nl_cache *) nl80211_genl_id; - rc = 0; -error_recvbuf: - free(recvbuf); -error: - return rc; -} - -/* Checks the netlink cache to find family reference by name string */ -/* NOTE: Caller needs to call genl_family_put() when done with * - * returned object */ -struct genl_family *genl_ctrl_search_by_name(struct nl_cache *cache, \ - const char *name) -{ - struct genl_family *gf = (struct genl_family *) \ - malloc(sizeof(struct genl_family)); - if (!gf) - goto fail; - memset(gf, 0, sizeof(*gf)); - - /* Add ref */ - gf->ce_refcnt++; - - /* Overriding cache pointer as family id for now */ - gf->gf_id = (uint16_t) ((uint32_t) cache); - strncpy(gf->gf_name, name, GENL_NAMSIZ); - - return gf; -fail: - return NULL; - -} - -int genl_ctrl_resolve(struct nl_sock *sk, const char *name) -{ - struct nl_cache *cache = NULL; - struct genl_family *gf = NULL; - int id = -1; - - /* Hack to support wpa_supplicant */ - if (strcmp(name, "nlctrl") == 0) - return NETLINK_GENERIC; - - if (strcmp(name, "nl80211") != 0) { - fprintf(stderr, "%s is not supported\n", name); - return id; - } - - if (!genl_ctrl_alloc_cache(sk, &cache)) { - gf = genl_ctrl_search_by_name(cache, name); - if (gf) - id = genl_family_get_id(gf); - } - - if (gf) - genl_family_put(gf); - if (cache) - nl_cache_free(cache); - - return id; -} |