Exemplo n.º 1
0
static int nlmsg_receive(char *buf, int len, int (*cb)(struct nlmsghdr *, void *), 
		int (*err_cb)(int, void *), void *arg)
{
	struct nlmsghdr *hdr;

	for (hdr = (struct nlmsghdr *)buf; NLMSG_OK(hdr, len); hdr = NLMSG_NEXT(hdr, len)) {
		if (hdr->nlmsg_seq != CR_NLMSG_SEQ)
			continue;
		if (hdr->nlmsg_type == NLMSG_DONE) {
			int *len = (int *)NLMSG_DATA(hdr);

			if (*len < 0) {
				pr_err("ERROR %d reported by netlink (%s)\n",
					*len, strerror(-*len));
				return *len;
			}

			return 0;
		}
		if (hdr->nlmsg_type == NLMSG_ERROR) {
			struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(hdr);

			if (hdr->nlmsg_len - sizeof(*hdr) < sizeof(struct nlmsgerr)) {
				pr_err("ERROR truncated\n");
				return -1;
			}

			if (err->error == 0)
				return 0;

			return err_cb(err->error, arg);
		}
		if (cb(hdr, arg))
			return -1;
	}

	return 1;
}
Exemplo n.º 2
0
int readNlSock(int sockFd, char *bufPtr, int seqNum, int pId){
	 struct nlmsghdr *nlHdr;
	  int readLen = 0, msgLen = 0;

	   do{
		     /* Recieve response from the kernel */
		     if((readLen = recv(sockFd, bufPtr, BUFSIZE - msgLen, 0)) < 0){
				    perror("SOCK READ: ");
					   return -1;
					     }
			  
			   nlHdr = (struct nlmsghdr *)bufPtr;

			     /* Check if the header is valid */
			     if((NLMSG_OK(nlHdr, readLen) == 0) || (nlHdr->nlmsg_type == NLMSG_ERROR))
					   {
						      perror("Error in recieved packet");
							     return -1;
								   }
				  
				   /* Check if the its the last message */
				   if(nlHdr->nlmsg_type == NLMSG_DONE) {
					      break;
						    }
				     else{
						    /* Else move the pointer to buffer appropriately */
						    bufPtr += readLen;
							   msgLen += readLen;
							     }
					  
					   /* Check if its a multi part message */
					   if((nlHdr->nlmsg_flags & NLM_F_MULTI) == 0) {
						      /* return if its not */
						     break;
							   }
					    } while((nlHdr->nlmsg_seq != seqNum) || (nlHdr->nlmsg_pid != pId));
	    return msgLen;
}
Exemplo n.º 3
0
static struct nlmsghdr *get_msg(void)
{
	struct nlmsghdr *nlh;
	int len;

	nlh = (struct nlmsghdr *)malloc(MAX_MSG_SIZE);
	if (NULL==nlh)
		return NULL;
	memset(nlh, 0, MAX_MSG_SIZE);

	len = recv(nl_sd, (void *)nlh, MAX_MSG_SIZE, 0);
	if (len < 0) {
		printf("RECEIVE FAILED with %d", errno);
		free(nlh);
		return NULL;
	}

	if (!(NLMSG_OK(nlh, (unsigned int)len))) {
		printf("RECEIVE FAILED, message too long\n");
		free(nlh);
		return NULL;
	}
	if (nlh->nlmsg_type == NLMSG_ERROR) {
		struct nlmsgerr *err = (struct nlmsgerr *) NLMSG_DATA(nlh);
		printf("RECEIVE FAILED with msg error %i (pid %d): %s\n",
		       err->error, nlh->nlmsg_pid, strerror(err->error * -1));
		if (hexdump && len > 0)
			hexprint((char *)nlh, len);
		free(nlh);
		return NULL;
	}
	if (hexdump) {
		printf("RECEIVED A MESSAGE: %d\n", len);
		hexprint((char *)nlh, nlh->nlmsg_len);
	}

	return nlh;
}
Exemplo n.º 4
0
void process_netlink_msg(int sock)
{
	int len;
	char buf[4096];
	struct iovec iov = { buf, sizeof(buf) };
	struct sockaddr_nl sa;
	struct msghdr msg = { (void *)&sa, sizeof(sa), &iov, 1, NULL, 0, 0 };
	struct nlmsghdr *nh;
	struct ifinfomsg * ifinfo;
	char ifname[IF_NAMESIZE] = {""};

	len = recvmsg (sock, &msg, 0);
	if (len == -1) {
		flog(LOG_ERR, "recvmsg failed: %s", strerror(errno));
	}

	for (nh = (struct nlmsghdr *) buf; NLMSG_OK (nh, len); nh = NLMSG_NEXT (nh, len)) {
		/* The end of multipart message. */
		if (nh->nlmsg_type == NLMSG_DONE)
			return;

		if (nh->nlmsg_type == NLMSG_ERROR) {
			flog(LOG_ERR, "%s:%d Some type of netlink error.\n", __FILE__, __LINE__);
			abort();
		}

		/* Continue with parsing payload. */
		ifinfo = NLMSG_DATA(nh);
		if_indextoname(ifinfo->ifi_index, ifname);
		if (ifinfo->ifi_flags & IFF_RUNNING) {
			dlog(LOG_DEBUG, 3, "%s, ifindex %d, flags is running", ifname, ifinfo->ifi_index);
		}
		else {
			dlog(LOG_DEBUG, 3, "%s, ifindex %d, flags is *NOT* running", ifname, ifinfo->ifi_index);
		}
		reload_config();
	}
}
Exemplo n.º 5
0
void netlink_multicast(void)
{
  ssize_t len;
  struct nlmsghdr *h;
  int flags;
  
  /* don't risk blocking reading netlink messages here. */
  if ((flags = fcntl(daemon->netlinkfd, F_GETFL)) == -1 ||
      fcntl(daemon->netlinkfd, F_SETFL, flags | O_NONBLOCK) == -1) 
    return;
  
  if ((len = netlink_recv()) != -1)
    {
      for (h = (struct nlmsghdr *)iov.iov_base; NLMSG_OK(h, (size_t)len); h = NLMSG_NEXT(h, len))
	if (h->nlmsg_type == NLMSG_ERROR)
	  nl_err(h);
	else
	  nl_routechange(h);
    }

  /* restore non-blocking status */
  fcntl(daemon->netlinkfd, F_SETFL, flags); 
}
Exemplo n.º 6
0
/*
 * parse_netlink_msg
 */
void
parse_netlink_msg (char *buf, size_t buf_len)
{
  netlink_msg_ctx_t ctx_space, *ctx;
  struct nlmsghdr *hdr;
  int status;
  int len;

  ctx = &ctx_space;

  hdr = (struct nlmsghdr *) buf;
  len = buf_len;
  for (; NLMSG_OK (hdr, len); hdr = NLMSG_NEXT(hdr, len)) {

    netlink_msg_ctx_init(ctx);
    ctx->hdr = (struct nlmsghdr *) buf;

    switch (hdr->nlmsg_type) {

    case RTM_DELROUTE:
    case RTM_NEWROUTE:

      parse_route_msg(ctx);
      if (ctx->err_msg) {
	err_msg("Error parsing route message: %s", ctx->err_msg);
      }

      print_netlink_msg_ctx(ctx);
      break;

    default:
      trace(1, "Ignoring unknown netlink message - Type: %d", hdr->nlmsg_type);
    }

    netlink_msg_ctx_cleanup(ctx);
  }
}
Exemplo n.º 7
0
void adapterChangeObserverThread(void* aPtr)
{
    InterfaceChangedObserver* observer = (InterfaceChangedObserver*) aPtr;
    OsNetworkHandle *handle = observer->netHnd;
    char buffer[4096];
    struct nlmsghdr *nlh;
    int32_t len, ret;
    fd_set rfds,errfds;

    while (1) {
        if (SocketInterrupted(handle)) {
            return;
        }

        FD_ZERO(&rfds);
        FD_SET(handle->iPipe[0], &rfds);
        FD_SET(handle->iSocket, &rfds);

        FD_ZERO(&errfds);
        FD_SET(handle->iSocket, &errfds);

        ret = TEMP_FAILURE_RETRY_2(select(nfds(handle), &rfds, NULL, &errfds, NULL), handle);
        if ((ret > 0) && FD_ISSET(handle->iSocket, &rfds)) {
            nlh = (struct nlmsghdr *) buffer;
            if ((len = recv(handle->iSocket, nlh, 4096, 0)) > 0) {
                while (NLMSG_OK(nlh, len) && (nlh->nlmsg_type != NLMSG_DONE)) {
                    if (nlh->nlmsg_type == RTM_NEWADDR || 
                        nlh->nlmsg_type == RTM_DELADDR || 
                        nlh->nlmsg_type == RTM_NEWLINK) {              
                        observer->iCallback(observer->iArg);
                    }
                    nlh = NLMSG_NEXT(nlh, len);
                }
            }
        }
    }
}
Exemplo n.º 8
0
static int interpret(int p_socket, NetlinkList *p_netlinkList, struct ifaddrs **p_links, struct ifaddrs **p_resultList)
{
    pid_t l_pid = getpid();
    for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next)
    {
        unsigned int l_nlsize = p_netlinkList->m_size;
        struct nlmsghdr *l_hdr;
        for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize))
        {
            if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket)
            {
                continue;
            }
            
            if(l_hdr->nlmsg_type == NLMSG_DONE)
            {
                break;
            }
            
            if(l_hdr->nlmsg_type == RTM_NEWLINK)
            {
                if (interpretLink(l_hdr, p_links, p_resultList) == -1)
                {
                    return -1;
                }
            }
            else if(l_hdr->nlmsg_type == RTM_NEWADDR)
            {
                if (interpretAddr(l_hdr, p_links, p_resultList) == -1)
                {
                    return -1;
                }
            }
        }
    }
    return 0;
}
Exemplo n.º 9
0
/**
 * nfnl_process - process data coming from a nfnetlink system
 * @h: nfnetlink handler
 * @buf: buffer that contains the netlink message
 * @len: size of the data contained in the buffer (not the buffer size)
 *
 * This function processes all the nfnetlink messages contained inside a
 * buffer. It performs the appropiate sanity checks and passes the message
 * to a certain handler that is registered via register_callback().
 *
 * On success, NFNL_CB_STOP is returned if the data processing has finished.
 * If a value NFNL_CB_CONTINUE is returned, then there is more data to
 * process. On error, NFNL_CB_CONTINUE is returned and errno is set to the 
 * appropiate value.
 *
 * In case that the callback returns NFNL_CB_FAILURE, errno may be set by
 * the library client. If your callback decides not to process data anymore
 * for any reason, then it must return NFNL_CB_STOP. Otherwise, if the 
 * callback continues the processing NFNL_CB_CONTINUE is returned.
 */
int nfnl_process(struct nfnl_handle *h, const unsigned char *buf, size_t len)
{
	int ret = 0;
	struct nlmsghdr *nlh = (struct nlmsghdr *)buf;

	assert(h);
	assert(buf);
	assert(len > 0);

	/* check for out of sequence message */
	if (nlh->nlmsg_seq && nlh->nlmsg_seq != h->seq) {
		errno = EILSEQ;
		return -1;
	}
	while (len >= NLMSG_SPACE(0) && NLMSG_OK(nlh, len)) {

		ret = nfnl_step(h, nlh);
		if (ret <= NFNL_CB_STOP)
			break;

		nlh = NLMSG_NEXT(nlh, len);
	}
	return ret;
}
Exemplo n.º 10
0
void ifup_scan_event(struct nlmsghdr *nh, int len, int *seen_flags) {
    struct ifinfomsg *ifi;

    for (;NLMSG_OK(nh, len); nh = NLMSG_NEXT(nh, len)) {
	switch (nh->nlmsg_type) {
	    case NLMSG_DONE:
		return;

	    case NLMSG_ERROR:
		return;

	    case RTM_NEWLINK:
		ifi = NLMSG_DATA(nh);
		if (ifi->ifi_flags & IFF_RUNNING) {
		    *seen_flags |= SEEN_RUNNING;
		}
		break;

	    case RTM_NEWADDR:
		*seen_flags |= SEEN_ADDRESS;
		break;
	}
    }
}
Exemplo n.º 11
0
static void
netlink_new_msg(struct uloop_fd *ufd, unsigned events)
{
	struct nlmsghdr *nlh;
	char buffer[BUFSIZ];
	int msg_size;

	memset(&buffer, 0, sizeof(buffer));

	nlh = (struct nlmsghdr *)buffer;
	if ((msg_size = recv(ufd->fd, nlh, BUFSIZ, 0)) == -1) {
		DD("error receiving netlink message");
		return;
	}

	while (msg_size > sizeof(*nlh)) {
		int len = nlh->nlmsg_len;
		int req_len = len - sizeof(*nlh);

		if (req_len < 0 || len > msg_size) {
			DD("error reading netlink message");
			return;
		}

		if (!NLMSG_OK(nlh, msg_size)) {
			DD("netlink message is not NLMSG_OK");
			return;
		}

		if (nlh->nlmsg_type == RTM_NEWADDR)
			easycwmp_netlink_interface(nlh);

		msg_size -= NLMSG_ALIGN(len);
		nlh = (struct nlmsghdr*)((char*)nlh + NLMSG_ALIGN(len));
	}
}
static int
get_netlink(int fd, int flags,
	    int (*callback)(struct nlmsghdr *, const char *),
	    const char *ifname)
{
	char *buffer = NULL;
	ssize_t bytes;
	struct nlmsghdr *nlm;
	int r = -1;

	buffer = xzalloc(sizeof(char) * BUFFERLEN);
	for (;;) {
		bytes = recv(fd, buffer, BUFFERLEN, flags);
		if (bytes == -1) {
			if (errno == EAGAIN) {
				r = 0;
				goto eexit;
			}
			if (errno == EINTR)
				continue;
			goto eexit;
		}
		for (nlm = (struct nlmsghdr *)buffer;
		     NLMSG_OK(nlm, (size_t)bytes);
		     nlm = NLMSG_NEXT(nlm, bytes))
		{
			r = callback(nlm, ifname);
			if (r != 0)
				goto eexit;
		}
	}

eexit:
	free(buffer);
	return r;
}
Exemplo n.º 13
0
int nl_send(struct nl_handle *hnd, struct iovec *iov, int iovlen)
{
	struct sockaddr_nl sa = {
		.nl_family = AF_NETLINK,
	};
	struct msghdr msg = {
		.msg_name = &sa,
		.msg_namelen = sizeof(sa),
		.msg_iov = iov,
		.msg_iovlen = iovlen,
	};
	struct nlmsghdr *src = iov->iov_base;

	src->nlmsg_seq = ++hnd->seq;
	if (sendmsg(hnd->fd, &msg, 0) < 0)
		return errno;
	return 0;
}

int nl_recv(struct nl_handle *hnd, struct nlmsg_entry **dest, int is_dump)
{
	struct sockaddr_nl sa = {
		.nl_family = AF_NETLINK,
	};
	struct iovec iov;
	struct msghdr msg = {
		.msg_name = &sa,
		.msg_namelen = sizeof(sa),
		.msg_iov = &iov,
		.msg_iovlen = 1,
	};
	char buf[16384];
	int len, err;
	struct nlmsghdr *n;
	struct nlmsg_entry *ptr = NULL; /* GCC false positive */
	struct nlmsg_entry *entry;

	*dest = NULL;
	while (1) {
		iov.iov_base = buf;
		iov.iov_len = sizeof(buf);
		len = recvmsg(hnd->fd, &msg, 0);
		if (len < 0)
			return errno;
		if (!len)
			return EPIPE;
		if (sa.nl_pid) {
			/* not from the kernel */
			continue;
		}
		for (n = (struct nlmsghdr *)buf; NLMSG_OK(n, len); n = NLMSG_NEXT(n, len)) {
			if (n->nlmsg_pid != hnd->pid || n->nlmsg_seq != hnd->seq)
				continue;
			if (is_dump && n->nlmsg_type == NLMSG_DONE)
				return 0;
			if (n->nlmsg_type == NLMSG_ERROR) {
				struct nlmsgerr *nlerr = (struct nlmsgerr *)NLMSG_DATA(n);

				err = -nlerr->error;
				goto err_out;
			}
			entry = malloc(n->nlmsg_len + sizeof(void *));
			if (!entry) {
				err = ENOMEM;
				goto err_out;
			}
			entry->next = NULL;
			memcpy(&entry->h, n, n->nlmsg_len);
			if (!*dest)
				*dest = entry;
			else
				ptr->next = entry;
			ptr = entry;
			if (!is_dump)
				return 0;
		}
	}
err_out:
	nlmsg_free(*dest);
	*dest = NULL;
	return err;
}

int nl_exchange(struct nl_handle *hnd,
		struct nlmsghdr *src, struct nlmsg_entry **dest)
{
	struct iovec iov = {
		.iov_base = src,
		.iov_len = src->nlmsg_len,
	};
	int is_dump;
	int err;

	is_dump = !!(src->nlmsg_flags & NLM_F_DUMP);
	err = nl_send(hnd, &iov, 1);
	if (err)
		return err;
	return nl_recv(hnd, dest, is_dump);
}

/* The original payload is not freed. Returns 0 in case of error, length
 * of *dest otherwise. *dest is newly allocated. */
int nla_add_str(void *orig, int orig_len, int nla_type, const char *str,
		void **dest)
{
	struct nlattr *nla;
	int len = strlen(str) + 1;
	int size;

	size = NLA_ALIGN(orig_len) + NLA_HDRLEN + NLA_ALIGN(len);
	*dest = calloc(size, 1);
	if (!*dest)
		return 0;
	if (orig_len)
		memcpy(*dest, orig, orig_len);
	nla = *dest + NLA_ALIGN(orig_len);
	nla->nla_len = NLA_HDRLEN + len;
	nla->nla_type = nla_type;
	memcpy(nla + 1, str, len);
	return size;
}

int rtnl_open(struct nl_handle *hnd)
{
	return nl_open(hnd, NETLINK_ROUTE);
}

int rtnl_dump(struct nl_handle *hnd, int family, int type, struct nlmsg_entry **dest)
{
	struct {
		struct nlmsghdr n;
		struct ifinfomsg i;
	} req;

	memset(&req, 0, sizeof(req));
	req.n.nlmsg_len = sizeof(req);
	req.n.nlmsg_type = type;
	req.n.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST;
	req.i.ifi_family = family;
	return nl_exchange(hnd, &req.n, dest);
}

void rtnl_parse(struct rtattr *tb[], int max, struct rtattr *rta, int len)
{
	memset(tb, 0, sizeof(struct rtattr *) * (max + 1));
	while (RTA_OK(rta, len)) {
		if (rta->rta_type <= max)
			tb[rta->rta_type] = rta;
		rta = RTA_NEXT(rta, len);
	}
}

void rtnl_parse_nested(struct rtattr *tb[], int max, struct rtattr *rta)
{
	rtnl_parse(tb, max, RTA_DATA(rta), RTA_PAYLOAD(rta));
}

int genl_open(struct nl_handle *hnd)
{
	return nl_open(hnd, NETLINK_GENERIC);
}

int genl_request(struct nl_handle *hnd,
		 int type, int cmd, void *payload, int payload_len,
		 struct nlmsg_entry **dest)
{
	struct {
		struct nlmsghdr n;
		struct genlmsghdr g;
	} req;
	struct iovec iov[2];
	int err;

	memset(&req, 0, sizeof(req));
	req.n.nlmsg_len = sizeof(req) + payload_len;
	req.n.nlmsg_type = type;
	req.n.nlmsg_flags = NLM_F_REQUEST;
	req.g.cmd = cmd;
	req.g.version = 1;

	iov[0].iov_base = &req;
	iov[0].iov_len = sizeof(req);
	iov[1].iov_base = payload;
	iov[1].iov_len = payload_len;
	err = nl_send(hnd, iov, 2);
	if (err)
		return err;
	return nl_recv(hnd, dest, 0);
}

unsigned int genl_family_id(struct nl_handle *hnd, const char *name)
{
	unsigned int res = 0;
	struct nlattr *nla;
	int len;
	struct nlmsg_entry *dest;
	void *ptr;

	len = nla_add_str(NULL, 0, CTRL_ATTR_FAMILY_NAME, name, &ptr);
	if (!len)
		return 0;
	if (genl_request(hnd, GENL_ID_CTRL, CTRL_CMD_GETFAMILY,
			 ptr, len, &dest)) {
		free(ptr);
		return 0;
	}
	free(ptr);

	len = dest->h.nlmsg_len - NLMSG_HDRLEN - GENL_HDRLEN;
	ptr = (void *)&dest->h + NLMSG_HDRLEN + GENL_HDRLEN;

	while (len > NLA_HDRLEN) {
		nla = ptr;
		if (nla->nla_type == CTRL_ATTR_FAMILY_ID &&
		    nla->nla_len >= NLA_HDRLEN + 2) {
			res = *(uint16_t *)(nla + 1);
			break;
		}

		ptr += NLMSG_ALIGN(nla->nla_len);
		len -= NLMSG_ALIGN(nla->nla_len);
	}

	nlmsg_free(dest);
	return res;

}
Exemplo n.º 14
0
//send data to command socket and wait - blocking - for a reply (an error message or a data dump)
int KernelNetlinkProtocol::send_and_parse(const std::string& data)
{
    int ret = send_to(cmd_sock_, data, cmd_tx_buff_size_, reinterpret_cast<sockaddr*>(&cmd_peer_addr_));

    if (ret <= 0)
    {
        tnt::Log::warning("KernelNetlinkProtocol::send_and_parse: send_to returned ", ret);

        return ret;
    }

    //tnt::Log::info(colors::green, "\n==> KernelNetlinkProtocol sent new data (", ret, " bytes) to socket ", cmd_sock_);

    static std::vector<std::string> messages;
    static uint16_t multi_type;

    int error = 5;
    bool all = false;
    int dim = 0;

    while (!all)
    {
        dim = recv(cmd_sock_, cmd_rx_buffer_.data(), cmd_rx_buffer_.size(), 0);

        // sanity checks
        if (dim <= 0)
        {
            if (dim < -1)
            {
                tnt::Log::error("KernelNetlinkProtocol::send_and_parse: recv returned ", dim);
            }

            return dim;
        }

        //tnt::Log::info(colors::blue, "\n==> received new data from socket ", cmd_sock_, " (command socket)");

        std::string raw_input(cmd_rx_buffer_.data(), dim);
        size_t len = raw_input.size();
        size_t pos = 0;

        for (const nlmsghdr* nlh = reinterpret_cast<const nlmsghdr*>(raw_input.data()); NLMSG_OK(nlh, len); nlh = NLMSG_NEXT(nlh, len))
        {
            if (netlink_debug) print_nlmsghdr_info(nlh);

            pos += nlh->nlmsg_len;

            //tnt::Log::info(raw_input.size() - pos, " of ", raw_input.size()," bytes left");

            if (nlh->nlmsg_flags & NLM_F_MULTI)	// Multipart message
            {
                if (nlh->nlmsg_type == NLMSG_DONE)	// Multipart message ended, we can start parsing all the previous messages all together
                {
                    //tnt::Log::info(colors::green, "\n----> multipart ended, now parsing");

                    switch (multi_type)
                    {
                    case RTM_NEWLINK:
                        tnt::Application::raise(event::PortList(parse_multi<std::shared_ptr<NetworkPort>>(messages, link_parser)), this);
                        break;

                    case RTM_NEWADDR:
                        tnt::Application::raise(event::AddressList(parse_multi<AddressInfo>(messages, address_parser)), this);
                        break;

                    case RTM_NEWROUTE:
                        tnt::Application::raise(event::RouteList(parse_multi<RouteInfo>(messages, route_parser)), this);
                        break;

                    default:
                        break;
                    }

                    messages.clear();
                    error = 0;
                }
                else
                {
                    multi_type = nlh->nlmsg_type;
                    messages.push_back(raw_input.substr(pos - nlh->nlmsg_len, pos));

                    continue;	// do not parse yet, thus continue;
                }
            }
            else	// single message
            {
                //tnt::Log::info(colors::green, "\n----> single message, now parsing");

                if (nlh->nlmsg_type == NLMSG_ERROR)
                {
                    nlmsgerr* nl_err = reinterpret_cast<nlmsgerr*>(NLMSG_DATA(nlh));

                    if (nl_err->error)
                    {
                        tnt::Log::warning("error message, code: ", nl_err->error, "\tin reply to message ", type2string(nl_err->msg.nlmsg_type), ", sequence ", nl_err->msg.nlmsg_seq);
                    }
                    else
                    {
                        //tnt::Log::info("ACK message\tin reply to message ", type2string(nl_err->msg.nlmsg_type), ", sequence ", nl_err->msg.nlmsg_seq);
                    }

                    error = -(nl_err->error);
                }
            }

            all = true;
        }

        // sanity checks
        if (raw_input.size() - pos > 0)
        {
            tnt::Log::warning(colors::red, "unable to parse everything (", len, " bytes remaining)");
            raw_input = raw_input.substr(pos);
        }
        else
        {
            raw_input.clear();
        }
    }

    return error;
}
Exemplo n.º 15
0
int main(int argc, char **argv) {
	int opt, longidx, nlsock, rc;
	struct sockaddr_nl nladdr = {AF_NETLINK};
	socklen_t          nlalen;
	pid_t mypid;
	ssize_t bcount;
	char *called;
	void *rcvbuf;

	/* Isolate the base name of the program as invoked. */
	called = strrchr(argv[0], '/');
	if (!called)
		called = argv[0];

	/* Parse the given options, looking for the filtering mode. */
	while ((opt = getopt_long(argc, argv, my_short_opts, my_long_opts, &longidx)) != -1) {
		switch (opt) {
			case 'e':
				execflag = 1;
				break;
			case 'f':
				forkflag = 1;
				break;
			case 't':
				threadflag = 1;
				break;
			default:
				if (opt != 'h')
					fprintf(stderr, "%s: Invalid option '%c' !\n", called, opt);
				usage(called);
		}
	}

	/* If no filtering mode, bail out. */
	if (!(execflag || forkflag)) {
		fprintf(stderr, "%s: Missing required mode option!\n", called);
		usage(called);
	}

	/* Create the netlink socket */
	nlsock = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_CONNECTOR);
	if (nlsock == -1) {
		perror("Unable to open a netlink socket!");
		exit(1);
	}

	/* Attach to the process connector group */
	{
		nladdr.nl_pid = mypid = getpid();
		nladdr.nl_groups = CN_IDX_PROC;
		if (bind(nlsock, (struct sockaddr *)&nladdr, sizeof(nladdr))) {
			perror("Unable to bind to the process connector!");
			exit(1);
		}
	}

	/* Request the process messages */
	{
		enum proc_cn_mcast_op cnop  = PROC_CN_MCAST_LISTEN;
		struct cn_msg         cnmsg = {{CN_IDX_PROC, CN_VAL_PROC}, 0, 0, sizeof(cnop), 0};
		struct nlmsghdr       nlmsg = {NLMSG_LENGTH(sizeof cnmsg + sizeof cnop), NLMSG_DONE};
		char padding[16];
		struct iovec iov[4] = {
			{&nlmsg, sizeof(nlmsg)},
			{padding, NLMSG_LENGTH(0) - sizeof(nlmsg)},
			{&cnmsg, sizeof(cnmsg)},
			{&cnop, sizeof(cnop)}
		};
		nlmsg.nlmsg_pid = mypid;
		if ((bcount = writev(nlsock, iov, 4)) == -1) {
			perror("Unable to listen to the process connector!");
			exit(1);
		}
	}

	/* Receive messages forever ... */
	rcvbuf = malloc(4096+CONNECTOR_MAX_MSG_SIZE);
	if (!rcvbuf) {
		perror("Unable to allocate a receive buffer!");
		exit(1);
	}
	setbuf(stdout, NULL);
	while (1) {
		nlalen = sizeof(nladdr);
		bcount = recvfrom(nlsock, rcvbuf, 4096+CONNECTOR_MAX_MSG_SIZE,
			0, (struct sockaddr *)&nladdr, &nlalen);
		if (nladdr.nl_pid == 0) {
			struct nlmsghdr *hdr = rcvbuf;
			for (hdr=rcvbuf; NLMSG_OK(hdr, bcount); hdr=NLMSG_NEXT(hdr, bcount))
				dispatch_nl(hdr);
		}
	}
}
Exemplo n.º 16
0
/* ====================================================================== */
int getifaddrs(struct ifaddrs **ifap)
{
  int sd;
  struct nlmsg_list *nlmsg_list, *nlmsg_end, *nlm;
  /* - - - - - - - - - - - - - - - */
  int icnt;
  size_t dlen, xlen, nlen;
  uint32_t max_ifindex = 0;

  pid_t pid = getpid();
  int seq;
  int result;
  int build     ; /* 0 or 1 */

/* ---------------------------------- */
  /* initialize */
  icnt = dlen = xlen = nlen = 0;
  nlmsg_list = nlmsg_end = NULL;

  if (ifap)
    *ifap = NULL;

/* ---------------------------------- */
  /* open socket and bind */
  sd = nl_open();
  if (sd < 0)
    return -1;

/* ---------------------------------- */
   /* gather info */
  if ((seq = nl_getlist(sd, 0, RTM_GETLINK,
			&nlmsg_list, &nlmsg_end)) < 0){
    free_nlmsglist(nlmsg_list);
    nl_close(sd);
    return -1;
  }
  if ((seq = nl_getlist(sd, seq+1, RTM_GETADDR,
			&nlmsg_list, &nlmsg_end)) < 0){
    free_nlmsglist(nlmsg_list);
    nl_close(sd);
    return -1;
  }

/* ---------------------------------- */
  /* Estimate size of result buffer and fill it */
  for (build=0; build<=1; build++){
    struct ifaddrs *ifl = NULL, *ifa = NULL;
    struct nlmsghdr *nlh, *nlh0;
    void *data = NULL, *xdata = NULL, *ifdata = NULL;
    char *ifname = NULL, **iflist = NULL;
    uint16_t *ifflist = NULL;
    struct rtmaddr_ifamap ifamap;

    if (build){
      ifa = data = calloc(1,
			  NLMSG_ALIGN(sizeof(struct ifaddrs[icnt]))
			  + dlen + xlen + nlen);
      ifdata = calloc(1, 
		      NLMSG_ALIGN(sizeof(char *[max_ifindex+1]))
		      + NLMSG_ALIGN(sizeof(uint16_t [max_ifindex+1])));
      if (ifap != NULL)
	*ifap = (ifdata != NULL) ? ifa : NULL;
      else{
	free_data(data, ifdata);
	result = 0;
	break;
      }
      if (data == NULL || ifdata == NULL){
	free_data(data, ifdata);
	result = -1;
	break;
      }
      ifl = NULL;
      data += NLMSG_ALIGN(sizeof(struct ifaddrs)) * icnt;
      xdata = data + dlen;
      ifname = xdata + xlen;
      iflist = ifdata;
      ifflist = ((void *)iflist) + NLMSG_ALIGN(sizeof(char *[max_ifindex+1]));
    }

    for (nlm=nlmsg_list; nlm; nlm=nlm->nlm_next){
      int nlmlen = nlm->size;
      if (!(nlh0 = nlm->nlh))
	continue;
      for (nlh = nlh0; 
	   NLMSG_OK(nlh, nlmlen); 
	   nlh=NLMSG_NEXT(nlh,nlmlen)){
	struct ifinfomsg *ifim = NULL;
	struct ifaddrmsg *ifam = NULL;
	struct rtattr *rta;

	size_t nlm_struct_size = 0;
	sa_family_t nlm_family = 0;
	uint32_t nlm_scope = 0, nlm_index = 0;
#ifndef IFA_NETMASK
	size_t sockaddr_size = 0;
	uint32_t nlm_prefixlen = 0;
#endif
	size_t rtasize;

	memset(&ifamap, 0, sizeof(ifamap));

	/* check if the message is what we want */
	if (nlh->nlmsg_pid != pid ||
	    nlh->nlmsg_seq != nlm->seq)
	  continue;
	if (nlh->nlmsg_type == NLMSG_DONE){
	  break; /* ok */
	}
	switch (nlh->nlmsg_type){
	case RTM_NEWLINK:
	  ifim = (struct ifinfomsg *)NLMSG_DATA(nlh);
	  nlm_struct_size = sizeof(*ifim);
	  nlm_family = ifim->ifi_family;
	  nlm_scope = 0;
	  nlm_index = ifim->ifi_index;
	  nlm_prefixlen = 0;
	  if (build)
	    ifflist[nlm_index] = ifa->ifa_flags = ifim->ifi_flags;
	  break;
	case RTM_NEWADDR:
	  ifam = (struct ifaddrmsg *)NLMSG_DATA(nlh);
	  nlm_struct_size = sizeof(*ifam);
	  nlm_family = ifam->ifa_family;
	  nlm_scope = ifam->ifa_scope;
	  nlm_index = ifam->ifa_index;
	  nlm_prefixlen = ifam->ifa_prefixlen;
	  if (build)
	    ifa->ifa_flags = ifflist[nlm_index];
	  break;
	default:
	  continue;
	}
	
	if (!build){
	  if (max_ifindex < nlm_index)
	    max_ifindex = nlm_index;
	} else {
	  if (ifl != NULL)
	    ifl->ifa_next = ifa;
	}

	rtasize = NLMSG_PAYLOAD(nlh, nlmlen) - NLMSG_ALIGN(nlm_struct_size);
	for (rta = (struct rtattr *)(((char *)NLMSG_DATA(nlh)) + NLMSG_ALIGN(nlm_struct_size));
	     RTA_OK(rta, rtasize);
	     rta = RTA_NEXT(rta, rtasize)){
	  struct sockaddr **sap = NULL;
	  void *rtadata = RTA_DATA(rta);
	  size_t rtapayload = RTA_PAYLOAD(rta);
	  socklen_t sa_len;

	  switch(nlh->nlmsg_type){
	  case RTM_NEWLINK:
	    switch(rta->rta_type){
	    case IFLA_ADDRESS:
	    case IFLA_BROADCAST:
	      if (build){
		sap = (rta->rta_type == IFLA_ADDRESS) ? &ifa->ifa_addr : &ifa->ifa_broadaddr;
		*sap = (struct sockaddr *)data;
	      }
	      sa_len = ifa_sa_len(AF_PACKET, rtapayload);
	      if (rta->rta_type == IFLA_ADDRESS)
		sockaddr_size = NLMSG_ALIGN(sa_len);
	      if (!build){
		dlen += NLMSG_ALIGN(sa_len);
	      } else {
		memset(*sap, 0, sa_len);
		ifa_make_sockaddr(AF_PACKET, *sap, rtadata,rtapayload, 0,0);
		((struct sockaddr_ll *)*sap)->sll_ifindex = nlm_index;
		((struct sockaddr_ll *)*sap)->sll_hatype = ifim->ifi_type;
		data += NLMSG_ALIGN(sa_len);
	      }
	      break;
	    case IFLA_IFNAME:/* Name of Interface */
	      if (!build)
		nlen += NLMSG_ALIGN(rtapayload + 1);
	      else{
		ifa->ifa_name = ifname;
		if (iflist[nlm_index] == NULL)
		  iflist[nlm_index] = ifa->ifa_name;
		strncpy(ifa->ifa_name, rtadata, rtapayload);
		ifa->ifa_name[rtapayload] = '\0';
		ifname += NLMSG_ALIGN(rtapayload + 1);
	      }
	      break;
	    case IFLA_STATS:/* Statistics of Interface */
	      if (!build)
		xlen += NLMSG_ALIGN(rtapayload);
	      else{
		ifa->ifa_data = xdata;
		memcpy(ifa->ifa_data, rtadata, rtapayload);
		xdata += NLMSG_ALIGN(rtapayload);
	      }
	      break;
	    case IFLA_UNSPEC:
	      break;
	    case IFLA_MTU:
	      break;
	    case IFLA_LINK:
	      break;
	    case IFLA_QDISC:
	      break;
	    }
	    break;
	  case RTM_NEWADDR:
	    if (nlm_family == AF_PACKET) break;
	    switch(rta->rta_type){
	    case IFA_ADDRESS:
		ifamap.address = rtadata;
		ifamap.address_len = rtapayload;
		break;
	    case IFA_LOCAL:
		ifamap.local = rtadata;
		ifamap.local_len = rtapayload;
		break;
	    case IFA_BROADCAST:
		ifamap.broadcast = rtadata;
		ifamap.broadcast_len = rtapayload;
		break;
#ifdef HAVE_IFADDRS_IFA_ANYCAST
	    case IFA_ANYCAST:
		ifamap.anycast = rtadata;
		ifamap.anycast_len = rtapayload;
		break;
#endif
	    case IFA_LABEL:
	      if (!build)
		nlen += NLMSG_ALIGN(rtapayload + 1);
	      else{
		ifa->ifa_name = ifname;
		if (iflist[nlm_index] == NULL)
		  iflist[nlm_index] = ifname;
		strncpy(ifa->ifa_name, rtadata, rtapayload);
		ifa->ifa_name[rtapayload] = '\0';
		ifname += NLMSG_ALIGN(rtapayload + 1);
	      }
	      break;
	    case IFA_UNSPEC:
	      break;
	    case IFA_CACHEINFO:
	      break;
	    }
	  }
	}
	if (nlh->nlmsg_type == RTM_NEWADDR &&
	    nlm_family != AF_PACKET) {
	  if (!ifamap.local) {
	    ifamap.local = ifamap.address;
	    ifamap.local_len = ifamap.address_len;
	  }
	  if (!ifamap.address) {
	    ifamap.address = ifamap.local;
	    ifamap.address_len = ifamap.local_len;
	  }
	  if (ifamap.address_len != ifamap.local_len ||
	      (ifamap.address != NULL &&
	       memcmp(ifamap.address, ifamap.local, ifamap.address_len))) {
	    /* p2p; address is peer and local is ours */
	    ifamap.broadcast = ifamap.address;
	    ifamap.broadcast_len = ifamap.address_len;
	    ifamap.address = ifamap.local;
	    ifamap.address_len = ifamap.local_len;
	  }
	  if (ifamap.address) {
#ifndef IFA_NETMASK
	    sockaddr_size = NLMSG_ALIGN(ifa_sa_len(nlm_family,ifamap.address_len));
#endif
	    if (!build)
	      dlen += NLMSG_ALIGN(ifa_sa_len(nlm_family,ifamap.address_len));
	    else {
	      ifa->ifa_addr = (struct sockaddr *)data;
	      ifa_make_sockaddr(nlm_family, ifa->ifa_addr, ifamap.address, ifamap.address_len,
				nlm_scope, nlm_index);
	      data += NLMSG_ALIGN(ifa_sa_len(nlm_family, ifamap.address_len));
	    }
	  }
#ifdef IFA_NETMASK
	  if (ifamap.netmask) {
	    if (!build)
	      dlen += NLMSG_ALIGN(ifa_sa_len(nlm_family,ifamap.netmask_len));
	    else {
	      ifa->ifa_netmask = (struct sockaddr *)data;
	      ifa_make_sockaddr(nlm_family, ifa->ifa_netmask, ifamap.netmask, ifamap.netmask_len,
				nlm_scope, nlm_index);
	      data += NLMSG_ALIGN(ifa_sa_len(nlm_family, ifamap.netmask_len));
	    }
	  }
#endif
	  if (ifamap.broadcast) {
	    if (!build)
	      dlen += NLMSG_ALIGN(ifa_sa_len(nlm_family,ifamap.broadcast_len));
	    else {
	      ifa->ifa_broadaddr = (struct sockaddr *)data;
	      ifa_make_sockaddr(nlm_family, ifa->ifa_broadaddr, ifamap.broadcast, ifamap.broadcast_len,
				nlm_scope, nlm_index);
	      data += NLMSG_ALIGN(ifa_sa_len(nlm_family, ifamap.broadcast_len));
	    }
	  }
#ifdef HAVE_IFADDRS_IFA_ANYCAST
	  if (ifamap.anycast) {
	    if (!build)
	      dlen += NLMSG_ALIGN(ifa_sa_len(nlm_family,ifamap.anycast_len));
	    else {
	      ifa->ifa_anycast = (struct sockaddr *)data;
	      ifa_make_sockaddr(nlm_family, ifa->ifa_anyaddr, ifamap.anycast, ifamap.anycast_len,
				nlm_scope, nlm_index);
	      data += NLMSG_ALIGN(ifa_sa_len(nlm_family, ifamap.anycast_len));
	    }
	  }
#endif
	}
	if (!build){
#ifndef IFA_NETMASK
	  dlen += sockaddr_size;
#endif
	  icnt++;
	} else {
	  if (ifa->ifa_name == NULL)
	    ifa->ifa_name = iflist[nlm_index];
#ifndef IFA_NETMASK
	  if (ifa->ifa_addr && 
	      ifa->ifa_addr->sa_family != AF_UNSPEC && 
	      ifa->ifa_addr->sa_family != AF_PACKET){
	    ifa->ifa_netmask = (struct sockaddr *)data;
	    ifa_make_sockaddr_mask(ifa->ifa_addr->sa_family, ifa->ifa_netmask, nlm_prefixlen);
	  }
	  data += sockaddr_size;
#endif
	  ifl = ifa++;
	}
      }
    }
    if (!build){
      if (icnt == 0 && (dlen + nlen + xlen == 0)){
	if (ifap != NULL)
	  *ifap = NULL;
	break; /* cannot found any addresses */
      }
    }
    else
      free_data(NULL, ifdata);
  }

/* ---------------------------------- */
  /* Finalize */
  free_nlmsglist(nlmsg_list);
  nl_close(sd);
  return 0;
}
Exemplo n.º 17
0
	std::vector<ip_route> enum_routes(io_service& ios, error_code& ec)
	{
		std::vector<ip_route> ret;
	
#if TORRENT_USE_SYSCTL
/*
		struct rt_msg
		{
			rt_msghdr m_rtm;
			char buf[512];
		};

		rt_msg m;
		int len = sizeof(rt_msg);
		bzero(&m, len);
		m.m_rtm.rtm_type = RTM_GET;
		m.m_rtm.rtm_flags = RTF_UP | RTF_GATEWAY;
		m.m_rtm.rtm_version = RTM_VERSION;
		m.m_rtm.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
		m.m_rtm.rtm_seq = 0;
		m.m_rtm.rtm_msglen = len;

		int s = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC);
		if (s == -1)
		{
			ec = error_code(errno, asio::error::system_category);
			return std::vector<ip_route>();
		}

		int n = write(s, &m, len);
		if (n == -1)
		{
			ec = error_code(errno, asio::error::system_category);
			close(s);
			return std::vector<ip_route>();
		}
		else if (n != len)
		{
			ec = asio::error::operation_not_supported;
			close(s);
			return std::vector<ip_route>();
		}
		bzero(&m, len);

		n = read(s, &m, len);
		if (n == -1)
		{
			ec = error_code(errno, asio::error::system_category);
			close(s);
			return std::vector<ip_route>();
		}

		for (rt_msghdr* ptr = &m.m_rtm; (char*)ptr < ((char*)&m.m_rtm) + n; ptr = (rt_msghdr*)(((char*)ptr) + ptr->rtm_msglen))
		{
			std::cout << " rtm_msglen: " << ptr->rtm_msglen << std::endl;
			std::cout << " rtm_type: " << ptr->rtm_type << std::endl;
			if (ptr->rtm_errno)
			{
				ec = error_code(ptr->rtm_errno, asio::error::system_category);
				return std::vector<ip_route>();
			}
			if (m.m_rtm.rtm_flags & RTF_UP == 0
				|| m.m_rtm.rtm_flags & RTF_GATEWAY == 0)
			{
				ec = asio::error::operation_not_supported;
				return address_v4::any();
			}
			if (ptr->rtm_addrs & RTA_DST == 0
				|| ptr->rtm_addrs & RTA_GATEWAY == 0
				|| ptr->rtm_addrs & RTA_NETMASK == 0)
			{
				ec = asio::error::operation_not_supported;
				return std::vector<ip_route>();
			}
			if (ptr->rtm_msglen > len - ((char*)ptr - ((char*)&m.m_rtm)))
			{
				ec = asio::error::operation_not_supported;
				return std::vector<ip_route>();
			}
			int min_len = sizeof(rt_msghdr) + 2 * sizeof(sockaddr_in);
			if (m.m_rtm.rtm_msglen < min_len)
			{
				ec = asio::error::operation_not_supported;
				return std::vector<ip_route>();
			}

			ip_route r;
			// destination
			char* p = m.buf;
			sockaddr_in* sin = (sockaddr_in*)p;
			r.destination = sockaddr_to_address((sockaddr*)p);

			// gateway
			p += sin->sin_len;
			sin = (sockaddr_in*)p;
			r.gateway = sockaddr_to_address((sockaddr*)p);

			// netmask
			p += sin->sin_len;
			sin = (sockaddr_in*)p;
			r.netmask = sockaddr_to_address((sockaddr*)p);
			ret.push_back(r);
		}
		close(s);
*/
	int mib[6] = { CTL_NET, PF_ROUTE, 0, AF_UNSPEC, NET_RT_DUMP, 0};

	size_t needed = 0;
#ifdef TORRENT_OS2
	if (__libsocket_sysctl(mib, 6, 0, &needed, 0, 0) < 0)
#else
	if (sysctl(mib, 6, 0, &needed, 0, 0) < 0)
#endif
	{
		ec = error_code(errno, asio::error::system_category);
		return std::vector<ip_route>();
	}

	if (needed <= 0)
	{
		return std::vector<ip_route>();
	}

	boost::scoped_array<char> buf(new (std::nothrow) char[needed]);
	if (buf.get() == 0)
	{
		ec = asio::error::no_memory;
		return std::vector<ip_route>();
	}

#ifdef TORRENT_OS2
	if (__libsocket_sysctl(mib, 6, buf.get(), &needed, 0, 0) < 0)
#else
	if (sysctl(mib, 6, buf.get(), &needed, 0, 0) < 0)
#endif
	{
		ec = error_code(errno, asio::error::system_category);
		return std::vector<ip_route>();
	}

	char* end = buf.get() + needed;

	int s = socket(AF_INET, SOCK_DGRAM, 0);
	if (s < 0)
	{
		ec = error_code(errno, asio::error::system_category);
		return std::vector<ip_route>();
	}
	rt_msghdr* rtm;
	for (char* next = buf.get(); next < end; next += rtm->rtm_msglen)
	{
		rtm = (rt_msghdr*)next;
		if (rtm->rtm_version != RTM_VERSION)
			continue;
		
		ip_route r;
		if (parse_route(s, rtm, &r)) ret.push_back(r);
	}
	close(s);
	
#elif TORRENT_USE_GETIPFORWARDTABLE
/*
	move this to enum_net_interfaces
		// Load Iphlpapi library
		HMODULE iphlp = LoadLibraryA("Iphlpapi.dll");
		if (!iphlp)
		{
			ec = asio::error::operation_not_supported;
			return std::vector<ip_route>();
		}

		// Get GetAdaptersInfo() pointer
		typedef DWORD (WINAPI *GetAdaptersInfo_t)(PIP_ADAPTER_INFO, PULONG);
		GetAdaptersInfo_t GetAdaptersInfo = (GetAdaptersInfo_t)GetProcAddress(iphlp, "GetAdaptersInfo");
		if (!GetAdaptersInfo)
		{
			FreeLibrary(iphlp);
			ec = asio::error::operation_not_supported;
			return std::vector<ip_route>();
		}

		PIP_ADAPTER_INFO adapter_info = 0;
		ULONG out_buf_size = 0;
		if (GetAdaptersInfo(adapter_info, &out_buf_size) != ERROR_BUFFER_OVERFLOW)
		{
			FreeLibrary(iphlp);
			ec = asio::error::operation_not_supported;
			return std::vector<ip_route>();
		}

		adapter_info = (IP_ADAPTER_INFO*)malloc(out_buf_size);
		if (!adapter_info)
		{
			FreeLibrary(iphlp);
			ec = asio::error::no_memory;
			return std::vector<ip_route>();
		}

		if (GetAdaptersInfo(adapter_info, &out_buf_size) == NO_ERROR)
		{
			for (PIP_ADAPTER_INFO adapter = adapter_info;
				adapter != 0; adapter = adapter->Next)
			{

				ip_route r;
				r.destination = address::from_string(adapter->IpAddressList.IpAddress.String, ec);
				r.gateway = address::from_string(adapter->GatewayList.IpAddress.String, ec);
				r.netmask = address::from_string(adapter->IpAddressList.IpMask.String, ec);
				strncpy(r.name, adapter->AdapterName, sizeof(r.name));

				if (ec)
				{
					ec = error_code();
					continue;
				}
				ret.push_back(r);
			}
		}

		// Free memory
		free(adapter_info);
		FreeLibrary(iphlp);
*/

		// Load Iphlpapi library
		HMODULE iphlp = LoadLibraryA("Iphlpapi.dll");
		if (!iphlp)
		{
			ec = asio::error::operation_not_supported;
			return std::vector<ip_route>();
		}

		typedef DWORD (WINAPI *GetIfEntry_t)(PMIB_IFROW pIfRow);
		GetIfEntry_t GetIfEntry = (GetIfEntry_t)GetProcAddress(iphlp, "GetIfEntry");
		if (!GetIfEntry)
		{
			ec = asio::error::operation_not_supported;
			return std::vector<ip_route>();
		}

#if _WIN32_WINNT >= 0x0600
		typedef DWORD (WINAPI *GetIpForwardTable2_t)(
			ADDRESS_FAMILY, PMIB_IPFORWARD_TABLE2*);
		typedef void (WINAPI *FreeMibTable_t)(PVOID Memory);
			
		GetIpForwardTable2_t GetIpForwardTable2 = (GetIpForwardTable2_t)GetProcAddress(
			iphlp, "GetIpForwardTable2");
		FreeMibTable_t FreeMibTable = (FreeMibTable_t)GetProcAddress(
			iphlp, "FreeMibTable");
		if (GetIpForwardTable2 && FreeMibTable)
		{
			MIB_IPFORWARD_TABLE2* routes = NULL;
			int res = GetIpForwardTable2(AF_UNSPEC, &routes);
			if (res == NO_ERROR)
			{
				for (int i = 0; i < routes->NumEntries; ++i)
				{
					ip_route r;
					r.gateway = sockaddr_to_address((const sockaddr*)&routes->Table[i].NextHop);
					r.destination = sockaddr_to_address(
						(const sockaddr*)&routes->Table[i].DestinationPrefix.Prefix);
					r.netmask = build_netmask(routes->Table[i].SitePrefixLength
						, routes->Table[i].DestinationPrefix.Prefix.si_family);
					MIB_IFROW ifentry;
					ifentry.dwIndex = routes->Table[i].InterfaceIndex;
					if (GetIfEntry(&ifentry) == NO_ERROR)
					{
						wcstombs(r.name, ifentry.wszName, sizeof(r.name));
						r.mtu = ifentry.dwMtu;
						ret.push_back(r);
					}
				}
			}
			if (routes) FreeMibTable(routes);
			FreeLibrary(iphlp);
			return ret;
		}
#endif

		// Get GetIpForwardTable() pointer
		typedef DWORD (WINAPI *GetIpForwardTable_t)(PMIB_IPFORWARDTABLE pIpForwardTable,PULONG pdwSize,BOOL bOrder);
			
		GetIpForwardTable_t GetIpForwardTable = (GetIpForwardTable_t)GetProcAddress(
			iphlp, "GetIpForwardTable");
		if (!GetIpForwardTable)
		{
			FreeLibrary(iphlp);
			ec = asio::error::operation_not_supported;
			return std::vector<ip_route>();
		}

		MIB_IPFORWARDTABLE* routes = NULL;
		ULONG out_buf_size = 0;
		if (GetIpForwardTable(routes, &out_buf_size, FALSE) != ERROR_INSUFFICIENT_BUFFER)
		{
			FreeLibrary(iphlp);
			ec = asio::error::operation_not_supported;
			return std::vector<ip_route>();
		}

		routes = (MIB_IPFORWARDTABLE*)malloc(out_buf_size);
		if (!routes)
		{
			FreeLibrary(iphlp);
			ec = asio::error::no_memory;
			return std::vector<ip_route>();
		}

		if (GetIpForwardTable(routes, &out_buf_size, FALSE) == NO_ERROR)
		{
			for (int i = 0; i < routes->dwNumEntries; ++i)
			{
				ip_route r;
				r.destination = inaddr_to_address((in_addr const*)&routes->table[i].dwForwardDest);
				r.netmask = inaddr_to_address((in_addr const*)&routes->table[i].dwForwardMask);
				r.gateway = inaddr_to_address((in_addr const*)&routes->table[i].dwForwardNextHop);
				MIB_IFROW ifentry;
				ifentry.dwIndex = routes->table[i].dwForwardIfIndex;
				if (GetIfEntry(&ifentry) == NO_ERROR)
				{
					wcstombs(r.name, ifentry.wszName, sizeof(r.name));
					r.name[sizeof(r.name)-1] = 0;
					r.mtu = ifentry.dwMtu;
					ret.push_back(r);
				}
			}
		}

		// Free memory
		free(routes);
		FreeLibrary(iphlp);
#elif TORRENT_USE_NETLINK
		enum { BUFSIZE = 8192 };

		int sock = socket(PF_ROUTE, SOCK_DGRAM, NETLINK_ROUTE);
		if (sock < 0)
		{
			ec = error_code(errno, asio::error::system_category);
			return std::vector<ip_route>();
		}

		int seq = 0;

		char msg[BUFSIZE];
		memset(msg, 0, BUFSIZE);
		nlmsghdr* nl_msg = (nlmsghdr*)msg;

		nl_msg->nlmsg_len = NLMSG_LENGTH(sizeof(rtmsg));
		nl_msg->nlmsg_type = RTM_GETROUTE;
		nl_msg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST;
		nl_msg->nlmsg_seq = seq++;
		nl_msg->nlmsg_pid = getpid();

		if (send(sock, nl_msg, nl_msg->nlmsg_len, 0) < 0)
		{
			ec = error_code(errno, asio::error::system_category);
			close(sock);
			return std::vector<ip_route>();
		}

		int len = read_nl_sock(sock, msg, BUFSIZE, seq, getpid());
		if (len < 0)
		{
			ec = error_code(errno, asio::error::system_category);
			close(sock);
			return std::vector<ip_route>();
		}

		int s = socket(AF_INET, SOCK_DGRAM, 0);
		if (s < 0)
		{
			ec = error_code(errno, asio::error::system_category);
			return std::vector<ip_route>();
		}
		for (; NLMSG_OK(nl_msg, len); nl_msg = NLMSG_NEXT(nl_msg, len))
		{
			ip_route r;
			if (parse_route(s, nl_msg, &r)) ret.push_back(r);
		}
		close(s);
		close(sock);

#endif
		return ret;
	}
Exemplo n.º 18
0
	void Netlink::processNetlinkTelegram(void *pReadBuffer, size_t bufferSize) const
	{
		for (struct nlmsghdr *nh = reinterpret_cast <struct nlmsghdr *> (pReadBuffer); NLMSG_OK (nh, bufferSize); nh = NLMSG_NEXT (nh, bufferSize)) {
			if (nh->nlmsg_type == NLMSG_DONE) {
				// The end of multipart message.
				break;
			} else if (nh->nlmsg_type == NLMSG_ERROR) {
				::syslog(LOG_ERR, "error processing netlink events");
				break;
			} else {
				m_netadapterlist.update();
				switch(nh->nlmsg_type) {
				case RTM_NEWADDR:
					{
						struct ifaddrmsg* pIfaddrmsg = reinterpret_cast <struct ifaddrmsg*> (NLMSG_DATA(nh));
						if(pIfaddrmsg->ifa_family==AF_INET) {
							struct rtattr *rth = IFA_RTA(pIfaddrmsg);
							int rtl = IFA_PAYLOAD(nh);
							while (rtl && RTA_OK(rth, rtl)) {
								if (rth->rta_type == IFA_LOCAL) {
									// this is to be ignored if there are more than one ipv4 addresses assigned to the interface!
									try {
										communication::Netadapter adapter = m_netadapterlist.getAdapterByInterfaceIndex(pIfaddrmsg->ifa_index);
										if(adapter.getIpv4Addresses().size()==1) {
											if (m_eventHandler) {
												struct in_addr* pIn = reinterpret_cast < struct in_addr* > (RTA_DATA(rth));
												m_eventHandler(NEW, pIfaddrmsg->ifa_index, inet_ntoa(*pIn));
											}
										}
									} catch(const hbm::exception::exception&) {
									}
								}
								rth = RTA_NEXT(rth, rtl);
							}
						}
					}
					break;
				case RTM_DELADDR:
					{
						struct ifaddrmsg* pIfaddrmsg = reinterpret_cast <struct ifaddrmsg*> (NLMSG_DATA(nh));
						if(pIfaddrmsg->ifa_family==AF_INET) {
							struct rtattr *rth = IFA_RTA(pIfaddrmsg);
							int rtl = IFA_PAYLOAD(nh);
							while (rtl && RTA_OK(rth, rtl)) {
								if (rth->rta_type == IFA_LOCAL) {

									// this is to be ignored if there is another ipv4 address left for the interface!
									try {
										communication::Netadapter adapter = m_netadapterlist.getAdapterByInterfaceIndex(pIfaddrmsg->ifa_index);
										if(adapter.getIpv4Addresses().empty()==true) {
											if (m_eventHandler) {
												struct in_addr* pIn = reinterpret_cast < struct in_addr* > (RTA_DATA(rth));
												m_eventHandler(NEW, pIfaddrmsg->ifa_index, inet_ntoa(*pIn));
											}
										}
									} catch(const hbm::exception::exception&) {
									}
								}
								rth = RTA_NEXT(rth, rtl);
							}
						}
					}
					break;
				default:
					break;
				}
			}
		}
	}
Exemplo n.º 19
0
/*
 * See if left->addr or left->next is %defaultroute and change it to IP.
 *
 * Returns:
 * -1: failure
 *  0: done
 *  1: please call again: more to do
 */
static int resolve_defaultroute_one(struct starter_end *host,
				struct starter_end *peer)
{
	/*
	 * "left="         == host->addrtype and host->addr
	 * "leftnexthop="  == host->nexttype and host->nexthop
	 */

	/* What kind of result are we seeking? */
	bool seeking_src = (host->addrtype == KH_DEFAULTROUTE);
	bool seeking_gateway = (host->nexttype == KH_DEFAULTROUTE);

	char msgbuf[RTNL_BUFSIZE];
	bool has_dst = FALSE;
	int query_again = 0;

	if (!seeking_src && !seeking_gateway)
		return 0;	/* this end already figured out */

	/* Fill netlink request */
	netlink_query_init(msgbuf, host->addr_family);
	if (host->nexttype == KH_IPADDR) {
		/*
		 * My nexthop (gateway) is specified.
		 * We need to figure out our source IP to get there.
		 */
		netlink_query_add(msgbuf, RTA_DST, &host->nexthop);
		has_dst = TRUE;
	} else if (peer->addrtype == KH_IPADDR) {
		/*
		 * Peer IP is specified.
		 * We may need to figure out source IP
		 * and gateway IP to get there.
		 */
		netlink_query_add(msgbuf, RTA_DST, &peer->addr);
		has_dst = TRUE;
		if (seeking_src && seeking_gateway &&
			host->addr_family == AF_INET) {
			/*
			 * If we have only peer IP and no gateway/src we must
			 * do two queries:
			 * 1) find out gateway for dst
			 * 2) find out src for that gateway
			 * Doing both in one query returns src for dst.
			 *
			 * (IPv6 returns link-local for gateway so we can and
			 * do seek both in one query.)
			 */
			seeking_src = FALSE;
			query_again = 1;
		}
	}
	if (has_dst && host->addrtype == KH_IPADDR) {
		/* SRC works only with DST */
		netlink_query_add(msgbuf, RTA_SRC, &host->addr);
	}

	/*
	 * If we have for example host=%defaultroute + peer=%any
	 * (no destination) the netlink reply will be full routing table.
	 * We must do two queries:
	 * 1) find out default gateway
	 * 2) find out src for that default gateway
	 */
	if (!has_dst) {
		if (seeking_src && seeking_gateway) {
			seeking_src = FALSE;
			query_again = 1;
		}
	}
	if (seeking_gateway) {
		struct nlmsghdr *nlmsg = (struct nlmsghdr *)msgbuf;

		nlmsg->nlmsg_flags |= NLM_F_DUMP;
        }

	if (verbose)
		printf("\nseeking_src = %d, seeking_gateway = %d, has_dst = %d\n",
			seeking_src, seeking_gateway, has_dst);

	/* Send netlink get_route request */

	ssize_t len = netlink_query(msgbuf);

	if (len < 0)
		return -1;

	/* Parse reply */
	struct nlmsghdr *nlmsg = (struct nlmsghdr *)msgbuf;

	for (; NLMSG_OK(nlmsg, len); nlmsg = NLMSG_NEXT(nlmsg, len)) {
		struct rtmsg *rtmsg;
		struct rtattr *rtattr;
		int rtlen;
		char r_interface[IF_NAMESIZE+1];
		char r_source[ADDRTOT_BUF];
		char r_gateway[ADDRTOT_BUF];
		char r_destination[ADDRTOT_BUF];
		bool ignore;

		if (nlmsg->nlmsg_type == NLMSG_DONE)
			break;

		if (nlmsg->nlmsg_type == NLMSG_ERROR) {
			printf("netlink error\n");
			return -1;
			break;
		}

		/* ignore all but IPv4 and IPv6 */
		rtmsg = (struct rtmsg *) NLMSG_DATA(nlmsg);
		if (rtmsg->rtm_family != AF_INET &&
			rtmsg->rtm_family != AF_INET6)
			continue;

		/* Parse one route entry */
		r_interface[0] = r_interface[IF_NAMESIZE] = r_source[0] =
			r_gateway[0] = r_destination[0] = '\0';
		rtattr = (struct rtattr *) RTM_RTA(rtmsg);
		rtlen = RTM_PAYLOAD(nlmsg);
		for (;
			RTA_OK(rtattr, rtlen);
			rtattr = RTA_NEXT(rtattr, rtlen)) {
			switch (rtattr->rta_type) {
			case RTA_OIF:
				if_indextoname(*(int *)RTA_DATA(rtattr),
					r_interface);
				break;

			case RTA_PREFSRC:
				inet_ntop(rtmsg->rtm_family, RTA_DATA(rtattr),
					r_source, sizeof(r_source));
				break;

			case RTA_GATEWAY:
				inet_ntop(rtmsg->rtm_family, RTA_DATA(rtattr),
					r_gateway, sizeof(r_gateway));
				break;

			case RTA_DST:
				inet_ntop(rtmsg->rtm_family, RTA_DATA(rtattr),
					r_destination,
					sizeof(r_destination));
				break;
			}
		}

		/*
		 * Ignore if not main table.
		 * Ignore ipsecX or mastX interfaces.
		 */
		ignore = rtmsg->rtm_table != RT_TABLE_MAIN ||
			startswith(r_interface, "ipsec") ||
			startswith(r_interface, "mast");

		if (verbose) {
			printf("dst %s via %s dev %s src %s table %d%s\n",
				r_destination,
				r_gateway,
				r_interface,
				r_source, rtmsg->rtm_table,
				ignore ? "" : " (ignored)");
		}

		if (ignore)
			continue;

		if (seeking_src && r_source[0] != '\0') {
			err_t err = tnatoaddr(r_source, 0, rtmsg->rtm_family,
					&host->addr);

			if (err == NULL) {
				host->addrtype = KH_IPADDR;
				seeking_src = FALSE;
				if (verbose)
					printf("set addr: %s\n", r_source);
			} else if (verbose) {
				printf("unknown source results from kernel (%s): %s\n",
					r_source, err);
			}
		}

		if (seeking_gateway && r_destination[0] == '\0' &&
			(has_dst || r_source[0] == '\0')) {
			if (r_gateway[0] == '\0' && r_interface[0] != '\0') {
				/*
				 * Point-to-Point default gw without "via IP"
				 * Attempt to find r_gateway as the IP address
				 * on the interface.
				 */
				resolve_ppp_peer(r_interface, host->addr_family,
						 r_gateway);
			}
			if (r_gateway[0] != '\0') {
				err_t err = tnatoaddr(r_gateway, 0,
						rtmsg->rtm_family,
						&host->nexthop);

				if (err != NULL) {
					printf("unknown gateway results from kernel: %s\n",
						err);
				} else {
					/* Note: Use first even if multiple */
					host->nexttype = KH_IPADDR;
					seeking_gateway = FALSE;
					if (verbose)
						printf("set nexthop: %s\n",
							r_gateway);
				}
			}
		}
	}
	return query_again;
}
Exemplo n.º 20
0
Arquivo: nield.c Projeto: yumkam/nield
/*
 * parse messages in received notifications from kernel
 */
int parse_events(struct msghdr *mhdr)
{
    struct nlmsghdr *nlh;
    struct nlmsgerr *nle;
    int nlh_len;

    /* get netlink message header */
    nlh = mhdr->msg_iov->iov_base;
    nlh_len = mhdr->msg_iov->iov_len;

    /* parse netlink message type */
    for( ; NLMSG_OK(nlh, nlh_len); nlh = NLMSG_NEXT(nlh, nlh_len)) {
        switch(nlh->nlmsg_type) {
            /* interface link message */
            case RTM_NEWLINK:
            case RTM_DELLINK:
                parse_ifimsg(nlh);
                break;
            /* interface address message */
            case RTM_NEWADDR:
            case RTM_DELADDR:
                parse_ifamsg(nlh);
                break;
            /* neighbor discovery message */
            case RTM_NEWNEIGH:
            case RTM_DELNEIGH:
                parse_ndmsg(nlh);
                break;
            /* route message */
            case RTM_NEWROUTE:
            case RTM_DELROUTE:
                parse_rtmsg(nlh);
                break;
#ifdef HAVE_LINUX_FIB_RULES_H
            /* fib rule header */
            case RTM_NEWRULE:
            case RTM_DELRULE:
                parse_frhdr(nlh);
                break;
#endif
            /* traffic control header */
            case RTM_NEWQDISC:
            case RTM_DELQDISC:
            case RTM_NEWTCLASS:
            case RTM_DELTCLASS:
                parse_tcmsg_qdisc(nlh);
                break;
            case RTM_NEWTFILTER:
            case RTM_DELTFILTER:
                parse_tcmsg_filter(nlh);
                break;
            case RTM_NEWACTION:
            case RTM_DELACTION:
                parse_tcamsg(nlh);
                break;
            /* error message */
            case NLMSG_ERROR:
                nle = (struct nlmsgerr *)NLMSG_DATA(nlh);
                rec_log("error: %s: nlmsg error: %s",
                    __func__, strerror(nle->error));
                break;
            /* unknown message */
            default:
                rec_log("error: %s: unknown nlsmg_type: %d",
                    __func__, (int)nlh->nlmsg_type);
        }
    }

    return(0);
}
Exemplo n.º 21
0
static int rtnl_dump_filter(struct rtnl_handle *rth,
		int (*filter)(const struct sockaddr_nl *, struct nlmsghdr *n, void *),
		void *arg1/*,
		int (*junk)(struct sockaddr_nl *, struct nlmsghdr *n, void *),
		void *arg2*/)
{
	int retval = -1;
	char *buf = xmalloc(8*1024); /* avoid big stack buffer */
	struct sockaddr_nl nladdr;
	struct iovec iov = { buf, 8*1024 };

	while (1) {
		int status;
		struct nlmsghdr *h;

		struct msghdr msg = {
			(void*)&nladdr, sizeof(nladdr),
			&iov,	1,
			NULL,	0,
			0
		};

		status = recvmsg(rth->fd, &msg, 0);

		if (status < 0) {
			if (errno == EINTR)
				continue;
			bb_perror_msg("OVERRUN");
			continue;
		}
		if (status == 0) {
			bb_error_msg("EOF on netlink");
			goto ret;
		}
		if (msg.msg_namelen != sizeof(nladdr)) {
			bb_error_msg_and_die("sender address length == %d", msg.msg_namelen);
		}

		h = (struct nlmsghdr*)buf;
		while (NLMSG_OK(h, status)) {
			int err;

			if (nladdr.nl_pid != 0 ||
			    h->nlmsg_pid != rth->local.nl_pid ||
			    h->nlmsg_seq != rth->dump) {
//				if (junk) {
//					err = junk(&nladdr, h, arg2);
//					if (err < 0) {
//						retval = err;
//						goto ret;
//					}
//				}
				goto skip_it;
			}

			if (h->nlmsg_type == NLMSG_DONE) {
				goto ret_0;
			}
			if (h->nlmsg_type == NLMSG_ERROR) {
				struct nlmsgerr *l_err = (struct nlmsgerr*)NLMSG_DATA(h);
				if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) {
					bb_error_msg("ERROR truncated");
				} else {
					errno = -l_err->error;
					bb_perror_msg("RTNETLINK answers");
				}
				goto ret;
			}
			err = filter(&nladdr, h, arg1);
			if (err < 0) {
				retval = err;
				goto ret;
			}

 skip_it:
			h = NLMSG_NEXT(h, status);
		}
		if (msg.msg_flags & MSG_TRUNC) {
			bb_error_msg("message truncated");
			continue;
		}
		if (status) {
			bb_error_msg_and_die("remnant of size %d!", status);
		}
	} /* while (1) */
 ret_0:
	retval++; /* = 0 */
 ret:
	free(buf);
	return retval;
}
Exemplo n.º 22
0
int main(int argc, char *argv[])
{
	int c, rc, rep_len, aggr_len, len2;
	int cmd_type = TASKSTATS_CMD_ATTR_UNSPEC;
	__u16 id;
	__u32 mypid;

	struct nlattr *na;
	int nl_sd = -1;
	int len = 0;
	pid_t tid = 0;
	pid_t rtid = 0;

	int fd = 0;
	int count = 0;
	int write_file = 0;
	int maskset = 0;
	char *logfile = NULL;
	int loop = 0;
	int containerset = 0;
	char *containerpath = NULL;
	int cfd = 0;
	int forking = 0;
	sigset_t sigset;

	struct msgtemplate msg;

	while (!forking) {
		c = getopt(argc, argv, "qdiw:r:m:t:p:vlC:c:");
		if (c < 0)
			break;

		switch (c) {
		case 'd':
			printf("print delayacct stats ON\n");
			print_delays = 1;
			break;
		case 'i':
			printf("printing IO accounting\n");
			print_io_accounting = 1;
			break;
		case 'q':
			printf("printing task/process context switch rates\n");
			print_task_context_switch_counts = 1;
			break;
		case 'C':
			containerset = 1;
			containerpath = optarg;
			break;
		case 'w':
			logfile = strdup(optarg);
			printf("write to file %s\n", logfile);
			write_file = 1;
			break;
		case 'r':
			rcvbufsz = atoi(optarg);
			printf("receive buf size %d\n", rcvbufsz);
			if (rcvbufsz < 0)
				err(1, "Invalid rcv buf size\n");
			break;
		case 'm':
			strncpy(cpumask, optarg, sizeof(cpumask));
			cpumask[sizeof(cpumask) - 1] = '\0';
			maskset = 1;
			printf("cpumask %s maskset %d\n", cpumask, maskset);
			break;
		case 't':
			tid = atoi(optarg);
			if (!tid)
				err(1, "Invalid tgid\n");
			cmd_type = TASKSTATS_CMD_ATTR_TGID;
			break;
		case 'p':
			tid = atoi(optarg);
			if (!tid)
				err(1, "Invalid pid\n");
			cmd_type = TASKSTATS_CMD_ATTR_PID;
			break;
		case 'c':

			/* Block SIGCHLD for sigwait() later */
			if (sigemptyset(&sigset) == -1)
				err(1, "Failed to empty sigset");
			if (sigaddset(&sigset, SIGCHLD))
				err(1, "Failed to set sigchld in sigset");
			sigprocmask(SIG_BLOCK, &sigset, NULL);

			/* fork/exec a child */
			tid = fork();
			if (tid < 0)
				err(1, "Fork failed\n");
			if (tid == 0)
				if (execvp(argv[optind - 1],
				    &argv[optind - 1]) < 0)
					exit(-1);

			/* Set the command type and avoid further processing */
			cmd_type = TASKSTATS_CMD_ATTR_PID;
			forking = 1;
			break;
		case 'v':
			printf("debug on\n");
			dbg = 1;
			break;
		case 'l':
			printf("listen forever\n");
			loop = 1;
			break;
		default:
			usage();
			exit(-1);
		}
	}

	if (write_file) {
		fd = open(logfile, O_WRONLY | O_CREAT | O_TRUNC,
			  S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
		if (fd == -1) {
			perror("Cannot open output file\n");
			exit(1);
		}
	}

	nl_sd = create_nl_socket(NETLINK_GENERIC);
	if (nl_sd < 0)
		err(1, "error creating Netlink socket\n");


	mypid = getpid();
	id = get_family_id(nl_sd);
	if (!id) {
		fprintf(stderr, "Error getting family id, errno %d\n", errno);
		goto err;
	}
	PRINTF("family id %d\n", id);

	if (maskset) {
		rc = send_cmd(nl_sd, id, mypid, TASKSTATS_CMD_GET,
			      TASKSTATS_CMD_ATTR_REGISTER_CPUMASK,
			      &cpumask, strlen(cpumask) + 1);
		PRINTF("Sent register cpumask, retval %d\n", rc);
		if (rc < 0) {
			fprintf(stderr, "error sending register cpumask\n");
			goto err;
		}
	}

	if (tid && containerset) {
		fprintf(stderr, "Select either -t or -C, not both\n");
		goto err;
	}

	/*
	 * If we forked a child, wait for it to exit. Cannot use waitpid()
	 * as all the delicious data would be reaped as part of the wait
	 */
	if (tid && forking) {
		int sig_received;
		sigwait(&sigset, &sig_received);
	}

	if (tid) {
		rc = send_cmd(nl_sd, id, mypid, TASKSTATS_CMD_GET,
			      cmd_type, &tid, sizeof(__u32));
		PRINTF("Sent pid/tgid, retval %d\n", rc);
		if (rc < 0) {
			fprintf(stderr, "error sending tid/tgid cmd\n");
			goto done;
		}
	}

	if (containerset) {
		cfd = open(containerpath, O_RDONLY);
		if (cfd < 0) {
			perror("error opening container file");
			goto err;
		}
		rc = send_cmd(nl_sd, id, mypid, CGROUPSTATS_CMD_GET,
			      CGROUPSTATS_CMD_ATTR_FD, &cfd, sizeof(__u32));
		if (rc < 0) {
			perror("error sending cgroupstats command");
			goto err;
		}
	}
	if (!maskset && !tid && !containerset) {
		usage();
		goto err;
	}

	do {
		rep_len = recv(nl_sd, &msg, sizeof(msg), 0);
		PRINTF("received %d bytes\n", rep_len);

		if (rep_len < 0) {
			fprintf(stderr, "nonfatal reply error: errno %d\n",
				errno);
			continue;
		}
		if (msg.n.nlmsg_type == NLMSG_ERROR ||
		    !NLMSG_OK((&msg.n), rep_len)) {
			struct nlmsgerr *err = NLMSG_DATA(&msg);
			fprintf(stderr, "fatal reply error,  errno %d\n",
				err->error);
			goto done;
		}

		PRINTF("nlmsghdr size=%zu, nlmsg_len=%d, rep_len=%d\n",
		       sizeof(struct nlmsghdr), msg.n.nlmsg_len, rep_len);


		rep_len = GENLMSG_PAYLOAD(&msg.n);

		na = (struct nlattr *) GENLMSG_DATA(&msg);
		len = 0;
		while (len < rep_len) {
			len += NLA_ALIGN(na->nla_len);
			switch (na->nla_type) {
			case TASKSTATS_TYPE_AGGR_TGID:
				/* Fall through */
			case TASKSTATS_TYPE_AGGR_PID:
				aggr_len = NLA_PAYLOAD(na->nla_len);
				len2 = 0;
				/* For nested attributes, na follows */
				na = (struct nlattr *) NLA_DATA(na);
				done = 0;
				while (len2 < aggr_len) {
					switch (na->nla_type) {
					case TASKSTATS_TYPE_PID:
						rtid = *(int *) NLA_DATA(na);
						if (print_delays)
							printf("PID\t%d\n", rtid);
						break;
					case TASKSTATS_TYPE_TGID:
						rtid = *(int *) NLA_DATA(na);
						if (print_delays)
							printf("TGID\t%d\n", rtid);
						break;
					case TASKSTATS_TYPE_STATS:
						count++;
						if (print_delays)
							print_delayacct((struct taskstats *) NLA_DATA(na));
						if (print_io_accounting)
							print_ioacct((struct taskstats *) NLA_DATA(na));
						if (print_task_context_switch_counts)
							task_context_switch_counts((struct taskstats *) NLA_DATA(na));
						if (fd) {
							if (write(fd, NLA_DATA(na), na->nla_len) < 0) {
								err(1,"write error\n");
							}
						}
						if (!loop)
							goto done;
						break;
					case TASKSTATS_TYPE_NULL:
						break;
					default:
						fprintf(stderr, "Unknown nested"
							" nla_type %d\n",
							na->nla_type);
						break;
					}
					len2 += NLA_ALIGN(na->nla_len);
					na = (struct nlattr *)((char *)na +
							       NLA_ALIGN(na->nla_len));
				}
				break;

			case CGROUPSTATS_TYPE_CGROUP_STATS:
				print_cgroupstats(NLA_DATA(na));
				break;
			default:
				fprintf(stderr, "Unknown nla_type %d\n",
					na->nla_type);
			case TASKSTATS_TYPE_NULL:
				break;
			}
			na = (struct nlattr *) (GENLMSG_DATA(&msg) + len);
		}
	} while (loop);
done:
	if (maskset) {
		rc = send_cmd(nl_sd, id, mypid, TASKSTATS_CMD_GET,
			      TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK,
			      &cpumask, strlen(cpumask) + 1);
		printf("Sent deregister mask, retval %d\n", rc);
		if (rc < 0)
			err(rc, "error sending deregister cpumask\n");
	}
err:
	close(nl_sd);
	if (fd)
		close(fd);
	if (cfd)
		close(cfd);
	return 0;
}
Exemplo n.º 23
0
// Source-compatible with the BSD function.
int getifaddrs(ifaddrs** result) {

    // Simplify cleanup for callers.
    *result = NULL;

    // Create a netlink socket.
    ScopedFd fd(socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE));
    if (fd.get() < 0) {
        return -1;
    }

    // Ask for the address information.
    addrReq_struct addrRequest;
    memset(&addrRequest, 0, sizeof(addrRequest));
    addrRequest.netlinkHeader.nlmsg_flags = NLM_F_REQUEST | NLM_F_MATCH;
    addrRequest.netlinkHeader.nlmsg_type = RTM_GETADDR;
    addrRequest.netlinkHeader.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(addrRequest)));
    addrRequest.msg.ifa_family = AF_UNSPEC; // All families.
    addrRequest.msg.ifa_index = 0; // All interfaces.
    if (!sendNetlinkMessage(fd.get(), &addrRequest, addrRequest.netlinkHeader.nlmsg_len)) {
        return -1;
    }
    
    // Read the responses.
    LocalArray<0> buf(65536); // We don't necessarily have std::vector.
    ssize_t bytesRead;
    while ((bytesRead  = recvNetlinkMessage(fd.get(), &buf[0], buf.size())) > 0) {
        nlmsghdr* hdr = reinterpret_cast<nlmsghdr*>(&buf[0]);
        for (; NLMSG_OK(hdr, (unsigned int)bytesRead); hdr = NLMSG_NEXT(hdr, bytesRead)) {
            switch (hdr->nlmsg_type) {
            case NLMSG_DONE:
            {
                return 0;
            }
            case NLMSG_ERROR:
            {
                return -1;
            }
            case RTM_NEWADDR:
                {
                    ifaddrmsg* address = reinterpret_cast<ifaddrmsg*>(NLMSG_DATA(hdr));
                    rtattr* rta = IFA_RTA(address);
                    size_t ifaPayloadLength = IFA_PAYLOAD(hdr);
                    while (RTA_OK(rta, ifaPayloadLength)) {
                        if (rta->rta_type == IFA_LOCAL) {
                            unsigned char family = address->ifa_family;
                            if (family == AF_INET || family == AF_INET6) {
                                *result = new ifaddrs(*result);
                                if (!(*result)->setNameAndFlagsByIndex(address->ifa_index)) {
                                    return -1;
                                }
                                (*result)->setAddress(family, RTA_DATA(rta), RTA_PAYLOAD(rta));
                                (*result)->setNetmask(family, address->ifa_prefixlen);
                            }
                        }
                        rta = RTA_NEXT(rta, ifaPayloadLength);
                    }
                }
                break;
            }
        }
    }
    // We only get here if recv fails before we see a NLMSG_DONE.
    return -1;
}
Exemplo n.º 24
0
static int
nl_getmsg (int sd, int request, int seq, pid_t pid, struct nlmsghdr **nlhp, int *done)
{
  struct nlmsghdr *nh;
  size_t bufsize = 65536, lastbufsize = 0;
  void *buff = NULL;
  int result = 0, read_size;
  int msg_flags;
  for (;;)
    {
      void *newbuff = realloc (buff, bufsize);
      if (newbuff == NULL || bufsize < lastbufsize)
	{
	  result = -1;
	  break;
	}
      buff = newbuff;
      result = read_size =
	nl_recvmsg (sd, request, seq, buff, bufsize, &msg_flags);
      if (read_size < 0 || (msg_flags & MSG_TRUNC))
	{
	  lastbufsize = bufsize;
	  bufsize *= 2;
	  continue;
	}
      if (read_size == 0)
	break;
      nh = (struct nlmsghdr *) buff;
      for (nh = (struct nlmsghdr *) buff;
	   NLMSG_OK (nh, read_size);
	   nh = (struct nlmsghdr *) NLMSG_NEXT (nh, read_size))
	{
	  if (nh->nlmsg_pid != pid || nh->nlmsg_seq != seq)
	    continue;
	  if (nh->nlmsg_type == NLMSG_DONE)
	    {
	      (*done)++;
	      break;		/* ok */
	    }
	  if (nh->nlmsg_type == NLMSG_ERROR)
	    {
	      struct nlmsgerr *nlerr = (struct nlmsgerr *) NLMSG_DATA (nh);
	      result = -1;
	      if (nh->nlmsg_len < NLMSG_LENGTH (sizeof (struct nlmsgerr)))
		__set_errno (EIO);
	      else
		__set_errno (-nlerr->error);
	      break;
	    }
	}
      break;
    }
  if (result < 0)
    if (buff)
      {
	int saved_errno = errno;
	free (buff);
	__set_errno (saved_errno);
      }
  *nlhp = (struct nlmsghdr *) buff;
  return result;
}
Exemplo n.º 25
0
static int genetlink_call(__u16 family_id, __u8 cmd, void *header,
                          size_t header_len, void *request, size_t request_len,
                          void *reply, size_t reply_len)
{
	struct msg {
		struct nlmsghdr n;
		struct genlmsghdr g;
		char payload[0];
	};

	struct msg *request_msg;
	struct msg *reply_msg;
	int request_msg_size;
	int reply_msg_size;

	struct sockaddr_nl local;
	struct pollfd pfd;
	int sndbuf = 32*1024; /* 32k */
	int rcvbuf = 32*1024; /* 32k */
	int len;
	int sk;

	/*
	 * Prepare request/reply messages
	 */
	request_msg_size = NLMSG_LENGTH(GENL_HDRLEN + header_len + request_len);
	request_msg = malloc(request_msg_size);
	request_msg->n.nlmsg_len = request_msg_size;
	request_msg->n.nlmsg_type = family_id;
	request_msg->n.nlmsg_flags = NLM_F_REQUEST;
	request_msg->n.nlmsg_seq = 0;
	request_msg->n.nlmsg_pid = getpid();
	request_msg->g.cmd = cmd;
	request_msg->g.version = 0;
	if (header_len)
		memcpy(&request_msg->payload[0], header, header_len);
	if (request_len)
		memcpy(&request_msg->payload[header_len], request, request_len);

	reply_msg_size = NLMSG_LENGTH(GENL_HDRLEN + header_len + reply_len);
	reply_msg = malloc(reply_msg_size);

	/*
	 * Create socket
	 */
	memset(&local, 0, sizeof(local));
	local.nl_family = AF_NETLINK;

	if ((sk = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_GENERIC)) == -1)
		fatal("error creating Netlink socket\n");

	if ((bind(sk, (struct sockaddr*)&local, sizeof(local)) == -1) ||
	                (setsockopt(sk, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf)) == -1) ||
	                (setsockopt(sk, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)) == -1)) {
		fatal("error creating Netlink socket\n");
	}

	/*
	 * Send request
	 */
	if (write_uninterrupted(sk, (char*)request_msg, request_msg_size) < 0)
		fatal("error sending message via Netlink\n");

	/*
	 * Wait for reply
	 */
	pfd.fd = sk;
	pfd.events = ~POLLOUT;
	if ((poll(&pfd, 1, 3000) != 1) || !(pfd.revents & POLLIN))
		fatal("no reply detected from Netlink\n");

	/*
	 * Read reply
	 */
	len = recv(sk, (char*)reply_msg, reply_msg_size, 0);
	if (len < 0)
		fatal("error receiving reply message via Netlink\n");

	close(sk);

	/*
	 * Validate response
	 */
	if (!NLMSG_OK(&reply_msg->n, len))
		fatal("invalid reply message received via Netlink\n");

	if (reply_msg->n.nlmsg_type == NLMSG_ERROR) {
		len = -1;
		goto out;
	}

	if ((request_msg->n.nlmsg_type != reply_msg->n.nlmsg_type) ||
	                (request_msg->n.nlmsg_seq != reply_msg->n.nlmsg_seq))
		fatal("unexpected message received via Netlink\n");

	/*
	 * Copy reply header
	 */
	len -= NLMSG_LENGTH(GENL_HDRLEN);
	if (len < header_len)
		fatal("too small reply message received via Netlink\n");
	if (header_len > 0)
		memcpy(header, &reply_msg->payload[0], header_len);

	/*
	 * Copy reply payload
	 */
	len -= header_len;
	if (len > reply_len)
		fatal("reply message too large to copy\n");
	if (len > 0)
		memcpy(reply, &reply_msg->payload[header_len], len);

out:
	free(request_msg);
	free(reply_msg);

	return len;
}
Exemplo n.º 26
0
/* Our netlink parser */
static int
netlink_parse_info(int (*filter) (struct sockaddr_nl *, struct nlmsghdr *),
		   nl_handle_t *nl, struct nlmsghdr *n)
{
	int status;
	int ret = 0;
	int error;

	while (1) {
		char buf[4096];
		struct iovec iov = { buf, sizeof buf };
		struct sockaddr_nl snl;
		struct msghdr msg =
		    { (void *) &snl, sizeof snl, &iov, 1, NULL, 0, 0 };
		struct nlmsghdr *h;

		status = recvmsg(nl->fd, &msg, 0);

		if (status < 0) {
			if (errno == EINTR)
				continue;
			if (errno == EWOULDBLOCK || errno == EAGAIN)
				break;
			log_message(LOG_INFO, "Netlink: Received message overrun (%m)");
			continue;
		}

		if (status == 0) {
			log_message(LOG_INFO, "Netlink: EOF");
			return -1;
		}

		if (msg.msg_namelen != sizeof snl) {
			log_message(LOG_INFO,
			       "Netlink: Sender address length error: length %d",
			       msg.msg_namelen);
			return -1;
		}

		for (h = (struct nlmsghdr *) buf; NLMSG_OK(h, status);
		     h = NLMSG_NEXT(h, status)) {
			/* Finish of reading. */
			if (h->nlmsg_type == NLMSG_DONE)
				return ret;

			/* Error handling. */
			if (h->nlmsg_type == NLMSG_ERROR) {
				struct nlmsgerr *err = (struct nlmsgerr *) NLMSG_DATA(h);

				/*
				 * If error == 0 then this is a netlink ACK.
				 * return if not related to multipart message.
				 */
				if (err->error == 0) {
					if (!(h->nlmsg_flags & NLM_F_MULTI))
						return 0;
					continue;
				}

				if (h->nlmsg_len < NLMSG_LENGTH(sizeof (struct nlmsgerr))) {
					log_message(LOG_INFO,
					       "Netlink: error: message truncated");
					return -1;
				}

				if (n && (err->error == -EEXIST) &&
				    ((n->nlmsg_type == RTM_NEWROUTE) ||
				     (n->nlmsg_type == RTM_NEWADDR)))
					return 0;

				log_message(LOG_INFO,
				       "Netlink: error: %s, type=(%u), seq=%u, pid=%d",
				       strerror(-err->error),
				       err->msg.nlmsg_type,
				       err->msg.nlmsg_seq, err->msg.nlmsg_pid);

				return -1;
			}

			/* Skip unsolicited messages from cmd channel */
			if (nl != &nl_cmd && h->nlmsg_pid == nl_cmd.snl.nl_pid)
				continue;

			error = (*filter) (&snl, h);
			if (error < 0) {
				log_message(LOG_INFO, "Netlink: filter function error");
				ret = error;
			}
		}

		/* After error care. */
		if (msg.msg_flags & MSG_TRUNC) {
			log_message(LOG_INFO, "Netlink: error: message truncated");
			continue;
		}
		if (status) {
			log_message(LOG_INFO, "Netlink: error: data remnant size %d",
			       status);
			return -1;
		}
	}

	return ret;
}
Exemplo n.º 27
0
/*
 * Adds or deletes an IP address on an interface.
 *
 * Action is one of:
 * - RTM_NEWADDR (to add a new address)
 * - RTM_DELADDR (to delete an existing address)
 *
 * Returns zero on success and negative errno on failure.
 */
int ifc_act_on_address(int action, const char *name, const char *address,
                       int prefixlen) {
    int ifindex, s, len, ret;
    struct sockaddr_storage ss;
    void *addr;
    size_t addrlen;
    struct {
        struct nlmsghdr n;
        struct ifaddrmsg r;
        // Allow for IPv6 address, headers, and padding.
        char attrbuf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
                     NLMSG_ALIGN(sizeof(struct rtattr)) +
                     NLMSG_ALIGN(INET6_ADDRLEN)];
    } req;
    struct rtattr *rta;
    struct nlmsghdr *nh;
    struct nlmsgerr *err;
    char buf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
             NLMSG_ALIGN(sizeof(struct nlmsgerr)) +
             NLMSG_ALIGN(sizeof(struct nlmsghdr))];

    // Get interface ID.
    ifindex = if_nametoindex(name);
    if (ifindex == 0) {
        return -errno;
    }

    // Convert string representation to sockaddr_storage.
    ret = string_to_ip(address, &ss);
    if (ret) {
        return ret;
    }

    // Determine address type and length.
    if (ss.ss_family == AF_INET) {
        struct sockaddr_in *sin = (struct sockaddr_in *) &ss;
        addr = &sin->sin_addr;
        addrlen = INET_ADDRLEN;
    } else if (ss.ss_family == AF_INET6) {
        struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &ss;
        addr = &sin6->sin6_addr;
        addrlen = INET6_ADDRLEN;
    } else {
        return -EAFNOSUPPORT;
    }

    // Fill in netlink structures.
    memset(&req, 0, sizeof(req));

    // Netlink message header.
    req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.r));
    req.n.nlmsg_type = action;
    req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
    req.n.nlmsg_pid = getpid();

    // Interface address message header.
    req.r.ifa_family = ss.ss_family;
    req.r.ifa_prefixlen = prefixlen;
    req.r.ifa_index = ifindex;

    // Routing attribute. Contains the actual IP address.
    rta = (struct rtattr *) (((char *) &req) + NLMSG_ALIGN(req.n.nlmsg_len));
    rta->rta_type = IFA_LOCAL;
    rta->rta_len = RTA_LENGTH(addrlen);
    req.n.nlmsg_len = NLMSG_ALIGN(req.n.nlmsg_len) + RTA_LENGTH(addrlen);
    memcpy(RTA_DATA(rta), addr, addrlen);

    s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
    if (send(s, &req, req.n.nlmsg_len, 0) < 0) {
        close(s);
        return -errno;
    }

    len = recv(s, buf, sizeof(buf), 0);
    close(s);
    if (len < 0) {
        return -errno;
    }

    // Parse the acknowledgement to find the return code.
    nh = (struct nlmsghdr *) buf;
    if (!NLMSG_OK(nh, (unsigned) len) || nh->nlmsg_type != NLMSG_ERROR) {
        return -EINVAL;
    }
    err = NLMSG_DATA(nh);

    // Return code is negative errno.
    return err->error;
}
Exemplo n.º 28
0
  int readPackets(HSP *sp)
  {
    int batch = 0;
    static uint32_t MySkipCount=1;
    if(sp->sFlow->sFlowSettings->ulogSubSamplingRate == 0) {
      // packet sampling was disabled by setting desired rate to 0
      return 0;
    }
    if(sp->ulog_soc) {
      for( ; batch < HSP_READPACKET_BATCH; batch++) {
	char buf[HSP_MAX_MSG_BYTES];
	socklen_t peerlen = sizeof(sp->ulog_peer);
	int len = recvfrom(sp->ulog_soc,
			   buf,
			   HSP_MAX_MSG_BYTES,
			   0,
			   (struct sockaddr *)&sp->ulog_peer,
			   &peerlen);
	if(len <= 0) break;
	if(debug > 1) myLog(LOG_INFO, "got ULOG msg: %u bytes", len);
	for(struct nlmsghdr *msg = (struct nlmsghdr *)buf; NLMSG_OK(msg, len); msg=NLMSG_NEXT(msg, len)) {

	  if(debug > 1) {
	    myLog(LOG_INFO, "netlink (%u bytes left) msg [len=%u type=%u flags=0x%x seq=%u pid=%u]",
		  len,
		  msg->nlmsg_len,
		  msg->nlmsg_type,
		  msg->nlmsg_flags,
		  msg->nlmsg_seq,
		  msg->nlmsg_pid);
	  }

	  switch(msg->nlmsg_type) {
	  case NLMSG_NOOP:
	  case NLMSG_ERROR:
	  case NLMSG_OVERRUN:
	    // ignore these
	    break;
	  case NLMSG_DONE: // last in multi-part
	  default:
	    {

	      if(--MySkipCount == 0) {
		/* reached zero. Set the next skip */
		MySkipCount = sfl_random((2 * sp->sFlow->sFlowSettings->ulogSubSamplingRate) - 1);

		/* and take a sample */

		// we're seeing type==111 on Fedora14
		//if(msg->nlmsg_flags & NLM_F_REQUEST) { }
		//if(msg->nlmsg_flags & NLM_F_MULTI) { }
		//if(msg->nlmsg_flags & NLM_F_ACK) { }
		//if(msg->nlmsg_flags & NLM_F_ECHO) { }
		ulog_packet_msg_t *pkt = NLMSG_DATA(msg);
		
		if(debug > 1) {
		  myLog(LOG_INFO, "mark=%u ts=%s hook=%u in=%s out=%s len=%u prefix=%s maclen=%u\n",
			pkt->mark,
			ctime(&pkt->timestamp_sec),
			pkt->hook,
			pkt->indev_name,
			pkt->outdev_name,
			pkt->data_len,
			pkt->prefix,
			pkt->mac_len);
		  if(pkt->mac_len == 14) {
		    u_char macdst[12], macsrc[12];
		    printHex(pkt->mac+6,6,macsrc,12,NO);
		    printHex(pkt->mac+0,6,macdst,12,NO);
		    uint16_t ethtype = (pkt->mac[12] << 8) + pkt->mac[13];
		    myLog(LOG_INFO, "%s -> %s (ethertype=0x%04X)", macsrc, macdst, ethtype);
		  }
		}

		
		SFL_FLOW_SAMPLE_TYPE fs = { 0 };
	
		SFLSampler *sampler = NULL;

		// set the ingress and egress ifIndex numbers.
		// Can be "INTERNAL" (0x3FFFFFFF) or "UNKNOWN" (0).
		if(pkt->indev_name[0]) {
		  SFLAdaptor *in = adaptorListGet(sp->adaptorList, pkt->indev_name);
		  if(in && in->ifIndex) {
		    fs.input = in->ifIndex;
		    sampler = getSampler(sp, pkt->indev_name, in->ifIndex);
		  }
		}
		else {
		  fs.input = SFL_INTERNAL_INTERFACE;
		}
		if(pkt->outdev_name[0]) {
		  SFLAdaptor *out = adaptorListGet(sp->adaptorList, pkt->outdev_name);
		  if(out && out->ifIndex) {
		    fs.output = out->ifIndex;
		    sampler = getSampler(sp, pkt->outdev_name, out->ifIndex);
		  }
		}
		else {
		  fs.output = SFL_INTERNAL_INTERFACE;
		}

		if(sampler == NULL) {
		  // maybe ULOG sent us a packet on device lo(?)
		  if(debug > 1) myLog(LOG_INFO, "dropped sample with no ifIndex\n");
		}
		else {
		  SFLFlow_sample_element hdrElem = { 0 };
		  hdrElem.tag = SFLFLOW_HEADER;
		  uint32_t FCS_bytes = 4;
		  uint32_t maxHdrLen = sampler->sFlowFsMaximumHeaderSize;
		  hdrElem.flowType.header.frame_length = pkt->data_len + FCS_bytes;
		  hdrElem.flowType.header.stripped = FCS_bytes;
		
		  u_char hdr[HSP_MAX_HEADER_BYTES];
		
		  if(pkt->mac_len == 14) {
		    // set the header_protocol to ethernet and
		    // reunite the mac header and payload in one buffer
		    hdrElem.flowType.header.header_protocol = SFLHEADER_ETHERNET_ISO8023;
		    memcpy(hdr, pkt->mac, 14);
		    maxHdrLen -= 14;
		    uint32_t payloadBytes = (pkt->data_len < maxHdrLen) ? pkt->data_len : maxHdrLen;
		    memcpy(hdr+14, pkt->payload, payloadBytes);
		    hdrElem.flowType.header.header_length = payloadBytes + 14;
		    hdrElem.flowType.header.header_bytes = hdr;
		    hdrElem.flowType.header.frame_length += 14;
		  }
		  else {
		    // no need to copy - just point at the payload
		    u_char ipversion = pkt->payload[0] >> 4;
		    if(ipversion != 4 && ipversion != 6) {
		      if(debug) myLog(LOG_ERR, "received non-IP packet. Encapsulation is unknown");
		    }
		    else {
		      hdrElem.flowType.header.header_protocol = (ipversion == 4) ? SFLHEADER_IPv4 : SFLHEADER_IPv6;
		      hdrElem.flowType.header.stripped += 14; // assume ethernet was (or will be) the framing
		      hdrElem.flowType.header.header_length = (pkt->data_len < maxHdrLen) ? pkt->data_len : maxHdrLen;
		      hdrElem.flowType.header.header_bytes = pkt->payload;
		    }
		  }
		
		  SFLADD_ELEMENT(&fs, &hdrElem);
		  // submit the actual sampling rate so it goes out with the sFlow feed
		  // otherwise the sampler object would fill in his own (sub-sampling) rate.
		  uint32_t actualSamplingRate = sp->sFlow->sFlowSettings->ulogActualSamplingRate;
		  fs.sampling_rate = actualSamplingRate;

		  // estimate the sample pool from the samples.  Could maybe do this
		  // above with the (possibly more granular) ulogSamplingRate, but then
		  // we would have to look up the sampler object every time, which
		  // might be too expensive in the case where ulogSamplingRate==1.
		  sampler->samplePool += actualSamplingRate;

		  sfl_sampler_writeFlowSample(sampler, &fs);
		}
	      }
	    }
	  } 
	}
      }
    }
Exemplo n.º 29
0
static gboolean can_read_data(GIOChannel *chan,
				GIOCondition cond, gpointer data)
{
	struct netlink_info *netlink = data;
	struct cmsghdr *cmsg;
	struct msghdr msg;
	struct iovec iov;
	struct nlmsghdr *nlmsg;
	unsigned char buffer[4096];
	unsigned char control[32];
	uint32_t group = 0;
	ssize_t len;
	int sk;

	sk = g_io_channel_unix_get_fd(chan);

	iov.iov_base = buffer;
	iov.iov_len = sizeof(buffer);

	memset(&msg, 0, sizeof(msg));
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;
	msg.msg_control = control;
	msg.msg_controllen = sizeof(control);

	len = recvmsg(sk, &msg, 0);
	if (len < 0)
		return FALSE;

	util_hexdump('>', buffer, len, netlink->debug_handler,
			netlink->debug_data);

	for (cmsg = CMSG_FIRSTHDR(&msg); cmsg;
					cmsg = CMSG_NXTHDR(&msg, cmsg)) {
		struct nl_pktinfo *pktinfo;

		if (cmsg->cmsg_level != SOL_NETLINK)
			continue;

		if (cmsg->cmsg_type != NETLINK_PKTINFO)
			continue;

		pktinfo = (void *) CMSG_DATA(cmsg);

		group = pktinfo->group;
	}

	for (nlmsg = iov.iov_base; NLMSG_OK(nlmsg, (uint32_t) len);
					nlmsg = NLMSG_NEXT(nlmsg, len)) {
		if (group > 0 && nlmsg->nlmsg_seq == 0) {
			process_broadcast(netlink, group, nlmsg);
			continue;
		}

		if (nlmsg->nlmsg_pid != netlink->pid)
			continue;

		if (nlmsg->nlmsg_flags & NLM_F_MULTI)
			process_multi(netlink, nlmsg);
		else
			process_message(netlink, nlmsg);
	}

	return TRUE;
}
Exemplo n.º 30
0
// man 7 netlink
int netlink_parse(int fd, int seq, netlink_cb_t callback, void *data)
{
	int len;
	int status;

	unsigned char buf[4096];
	struct sockaddr_nl snl;
	struct msghdr msg;
	struct iovec iov = { buf, sizeof(buf) };
	struct nlmsghdr *nh;

	memset(&snl, 0, sizeof(struct sockaddr_nl));
	snl.nl_family = AF_NETLINK;

	msg.msg_name = (void *)&snl;
	msg.msg_namelen = sizeof(struct sockaddr_nl);
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;
	msg.msg_control = NULL;
	msg.msg_controllen = 0;
	msg.msg_flags = 0;

	status = 0;

	do {
		len = recvmsg(fd, &msg, 0);
		dprintf("[%s] recvmsg returned %d", __FUNCTION__, len);

		if(len <= 0) {
			status = errno;
			dprintf("[%s] socket dead? bailing (%s)", __FUNCTION__, strerror(errno));
			break;
		}	

		if(msg.msg_flags & MSG_TRUNC) {
			dprintf("[%s] truncated message ? :(", __FUNCTION__);
			status = ERROR_NOT_SUPPORTED;
			break;
		}

		for(nh = (struct nlmsghdr *)(buf); NLMSG_OK(nh, len); nh = (struct nlmsghdr *) NLMSG_NEXT(nh, len)) {
			dprintf("[%s] buf = %p, nh = %p", __FUNCTION__, buf, nh);
			dprintf("[%s] nh->nlmsg_type = %d", __FUNCTION__, nh->nlmsg_type);

			if(nh->nlmsg_type == NLMSG_DONE) break;

			if(nh->nlmsg_type == NLMSG_ERROR) {
				struct nlmsgerr *me = (struct nlmsgerr *) NLMSG_DATA (nh);
				dprintf("[%s] in NLMSG_ERROR handling.. me = %p", __FUNCTION__, me);
				dprintf("[%s] me->error = %d", __FUNCTION__, me->error);
				if(me->error) {
					dprintf("[%s] so, we have: nlmsg_len: %d, nlmsg_type: %d, nlmsg_flags: %d, nlmsg_seq: %d, nlmsg_pid: %d", 
						__FUNCTION__, me->msg.nlmsg_len, me->msg.nlmsg_type, me->msg.nlmsg_flags,
						me->msg.nlmsg_seq, me->msg.nlmsg_pid);

					if(me->msg.nlmsg_seq == seq) {
						dprintf("[%s] Hum. kernel doesn't like our message :~(", __FUNCTION__);
						status = ERROR_NOT_SUPPORTED;
						break;
					}

					dprintf("[%s] don't know how to handle this error at the moment. continuing", __FUNCTION__);
				}
				continue; // "yea, whatever"
			}

			// 

			dprintf("[%s] dispatching into callback", __FUNCTION__);

			status = callback(nh, data);

			if(status) {
				dprintf("[%s] callback returned non zero(%d) , stopping process", __FUNCTION__, status);
				break;
			}

		}

	} while(0);


	return status;
}