Ejemplo n.º 1
0
static void netlink_receive_link(struct netlink_data *netlink,
				 void (*cb)(void *ctx, struct ifinfomsg *ifi,
					    u8 *buf, size_t len),
				 struct nlmsghdr *h)
{
	if (cb == NULL || NLMSG_PAYLOAD(h, 0) < sizeof(struct ifinfomsg))
		return;
	cb(netlink->cfg->ctx, NLMSG_DATA(h),
	   (u8 *) NLMSG_DATA(h) + NLMSG_ALIGN(sizeof(struct ifinfomsg)),
	   NLMSG_PAYLOAD(h, sizeof(struct ifinfomsg)));
}
Ejemplo n.º 2
0
static void genl_print_ctrl_family(struct nlmsghdr *hdr)
{
	struct genlmsghdr *genl = NLMSG_DATA(hdr);
	struct nlattr *attr = GEN_NLA(genl);
	uint32_t attrs_len = NLMSG_PAYLOAD(hdr, sizeof(struct genlmsghdr));

	for (; NLA_OK(attr, attrs_len); attr = NLA_NEXT(attr, attrs_len)) {
		switch (attr->nla_type) {
		case CTRL_ATTR_FAMILY_ID:
			nla_fmt(attr, "Family Id 0x%x", NLA_UINT16(attr));
			break;

		case CTRL_ATTR_FAMILY_NAME:
			nla_fmt(attr, "Family Name %s", NLA_STR(attr));
			break;

		case CTRL_ATTR_VERSION:
			nla_fmt(attr, "Version %u", NLA_UINT32(attr));
			break;

		case CTRL_ATTR_HDRSIZE:
			nla_fmt(attr, "Header size %u", NLA_UINT32(attr));
			break;

		case CTRL_ATTR_MAXATTR:
			nla_fmt(attr, "Max attr value 0x%x", NLA_UINT32(attr));
			break;

		default:
			nla_fmt(attr, "0x%x", attr->nla_type);
			break;
		}
	}
}
Ejemplo n.º 3
0
int connection_process(struct connection *conn, struct sk_buff *skb)
{
	int ret = 0;
	do {
		if (mutex_lock_interruptible(&(conn->data_lock))) {
			MCDRV_DBG_ERROR("Interrupted getting data semaphore!");
			ret = -1;
			break;
		}

		kfree_skb(conn->skb);

		/* Get a reference to the incomming skb */
		conn->skb = skb_get(skb);
		if (conn->skb) {
			conn->data_msg = nlmsg_hdr(conn->skb);
			conn->data_len = NLMSG_PAYLOAD(conn->data_msg, 0);
			conn->data_start = NLMSG_DATA(conn->data_msg);
			up(&(conn->data_available_sem));
		}
		mutex_unlock(&(conn->data_lock));
		ret = 0;
	} while (0);
	return ret;
}
Ejemplo n.º 4
0
static int handle_cmd(struct sk_buff *skb, struct genl_info *info)
{
	struct sk_buff *rep_buf;
	struct nlmsghdr *rep_nlh;
	struct nlmsghdr *req_nlh = info->nlhdr;
	struct tipc_genlmsghdr *req_userhdr = info->userhdr;
	int hdr_space = NLMSG_SPACE(GENL_HDRLEN + TIPC_GENL_HDRLEN);
	u16 cmd;

	if ((req_userhdr->cmd & 0xC000) && (!capable(CAP_NET_ADMIN)))
		cmd = TIPC_CMD_NOT_NET_ADMIN;
	else
		cmd = req_userhdr->cmd;

	rep_buf = tipc_cfg_do_cmd(req_userhdr->dest, cmd,
			NLMSG_DATA(req_nlh) + GENL_HDRLEN + TIPC_GENL_HDRLEN,
			NLMSG_PAYLOAD(req_nlh, GENL_HDRLEN + TIPC_GENL_HDRLEN),
			hdr_space);

	if (rep_buf) {
		skb_push(rep_buf, hdr_space);
		rep_nlh = nlmsg_hdr(rep_buf);
		memcpy(rep_nlh, req_nlh, hdr_space);
		rep_nlh->nlmsg_len = rep_buf->len;
		genlmsg_unicast(&init_net, rep_buf, NETLINK_CB(skb).pid);
	}

	return 0;
}
Ejemplo n.º 5
0
static void handle_message(const struct nlmsghdr *message, ssize_t len)
{
	uint8_t *payload;
	ssize_t length;
	struct nlattr *nlattr;
	struct ifaddrmsg *ifaddr;

	struct addrchange change;

	if (!NLMSG_OK(message, len)) {
		ERR("%s", "Got damaged message\n");
	}
	if (message->nlmsg_type != RTM_NEWADDR
	   && message->nlmsg_type != RTM_DELADDR) {
		INFO("%s", "Got unexpected message type");
		return;
	}

	ifaddr = (struct ifaddrmsg *)NLMSG_DATA(message);

	change.family = ifaddr->ifa_family;
	change.action = message->nlmsg_type;

	payload = (uint8_t *)(ifaddr + 1);
	length = NLMSG_PAYLOAD(message, sizeof(struct ifaddrmsg));

	for_each_nl(payload, nlattr, length) {
		handle_attr(nlattr, &change);
	}
Ejemplo n.º 6
0
static void
get_if_flags(struct nlmsghdr *nlm, int nlm_len, int request,
	     struct dhcp6_if *ifp) 
{
	struct ifinfomsg *ifim = (struct ifinfomsg *)NLMSG_DATA(nlm);
	struct rtattr *rta, *rta1;
	size_t rtasize, rtasize1, rtapayload;
	void *rtadata;

	dprintf(LOG_DEBUG, "get_if_flags called");

	if (ifim->ifi_family != AF_INET6 || nlm->nlmsg_type != request)
		return;
	if (ifim->ifi_index != ifp->ifid)
		return;
	rtasize = NLMSG_PAYLOAD(nlm, nlm_len) - NLMSG_ALIGN(sizeof(*ifim));
	for (rta = (struct rtattr *) (((char *) NLMSG_DATA(nlm)) +
	     NLMSG_ALIGN(sizeof(*ifim))); RTA_OK(rta, rtasize);
	     rta = RTA_NEXT(rta, rtasize)) {
	rtadata = RTA_DATA(rta);
	rtapayload = RTA_PAYLOAD(rta);
	
	switch(rta->rta_type) {
	case IFLA_IFNAME:
		break;
#ifdef IFLA_PROTINFO
	case IFLA_PROTINFO:
		rtasize1 = rta->rta_len;
		for (rta1 = (struct rtattr *)rtadata; RTA_OK(rta1, rtasize1);
		     rta1 = RTA_NEXT(rta1, rtasize1)) {
			void *rtadata1 = RTA_DATA(rta1);
			size_t rtapayload1= RTA_PAYLOAD(rta1);
			switch(rta1->rta_type) {
			case IFLA_INET6_CACHEINFO:
				break;
			case IFLA_INET6_FLAGS:
				/* flags for IF_RA_MANAGED/IF_RA_OTHERCONF */
				ifp->ra_flag = *((u_int32_t *)rtadata1);
				if (*((u_int32_t *)rtadata1) & IF_RA_MANAGED)
					dprintf(LOG_DEBUG, 
						"interface managed flags set");
				if (*((u_int32_t *)rtadata1) & IF_RA_OTHERCONF)
					dprintf(LOG_DEBUG,
						"interface otherconf flags set");
				break;
			default:
				break;
			}
		}
		break;
#endif
	default:
		break;
	}
	}
	return;
}
Ejemplo n.º 7
0
static void nl_link(struct nlmsghdr *nlmsg)
{
	int la;
	char ifname[IFNAMSIZ + 1];
	struct rtattr *a;
	struct ifinfomsg *i;

	if (nlmsg->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifinfomsg))) {
		_e("Packet too small or truncated!");
		return;
	}

	i  = NLMSG_DATA(nlmsg);
	a  = (struct rtattr *)((char *)i + NLMSG_ALIGN(sizeof(struct ifinfomsg)));
	la = NLMSG_PAYLOAD(nlmsg, sizeof(struct ifinfomsg));

	while (RTA_OK(a, la)) {
		if (a->rta_type == IFLA_IFNAME) {
			strlcpy(ifname, RTA_DATA(a), sizeof(ifname));
			switch (nlmsg->nlmsg_type) {
			case RTM_NEWLINK:
				/*
				 * New interface has appeared, or interface flags has changed.
				 * Check ifi_flags here to see if the interface is UP/DOWN
				 */
				_d("%s: New link, flags 0x%x, change 0x%x", ifname, i->ifi_flags, i->ifi_change);
				net_cond_set(ifname, "exist",   1);
				net_cond_set(ifname, "up",      i->ifi_flags & IFF_UP);
				net_cond_set(ifname, "running", i->ifi_flags & IFF_RUNNING);
				break;

			case RTM_DELLINK:
				/* NOTE: Interface has disappeared, not link down ... */
				_d("%s: Delete link", ifname);
				net_cond_set(ifname, "exist",   0);
				net_cond_set(ifname, "up",      0);
				net_cond_set(ifname, "running", 0);
				break;

			case RTM_NEWADDR:
				_d("%s: New Address", ifname);
				break;

			case RTM_DELADDR:
				_d("%s: Deconfig Address", ifname);
				break;

			default:
				_d("%s: Msg 0x%x", ifname, nlmsg->nlmsg_type);
				break;
			}
		}

		a = RTA_NEXT(a, la);
	}
}
Ejemplo n.º 8
0
// recv(fd [, type=0])
static PyObject* py_nl_recv(PyObject *self, PyObject *args, PyObject *keywds)
{
	int fd;
	int ret;
	unsigned char type = DEFAULT_RECV_TYPE;
	char buf[MAX_NL_BUFSIZ];
	PyObject *result = NULL;
	unsigned char *data;
	struct nlmsghdr *nlh;

	static char *kwlist[] = {"fd", "type", NULL};

	if (!PyArg_ParseTupleAndKeywords(args, keywds, "i|b", kwlist, &fd, &type)) {
		return None();
		//return NULL;
	}

	memset(buf, 0, MAX_NL_BUFSIZ);
	ret = recvfrom(fd, buf, MAX_NL_BUFSIZ, 0, NULL, NULL);
	if (ret < 0) {
		return None();
	}

	nlh = (struct nlmsghdr *)buf;
	data = (unsigned char *)NLMSG_DATA(nlh);

	if (NLMSG_PAYLOAD(nlh, 0) <= 1) {
		return None();
	}

	if (*data != type)  {
		return None();
	}

	result = Py_BuildValue("(s#kHHkk)", (char *)(data+1), (unsigned long)NLMSG_PAYLOAD(nlh, 0)-1,
			(unsigned long)NLMSG_PAYLOAD(nlh, 0)-1, (unsigned short)(nlh->nlmsg_type),
			(unsigned short)(nlh->nlmsg_flags), (unsigned long)(nlh->nlmsg_seq),
			(unsigned long)(nlh->nlmsg_pid));

	if (result)
		return result;
	return None();
}
//------------------------------------------------------------------------------
void NetlinkConnection::handleMessage(
    struct nlmsghdr *nlh
) {
	dataMutex.lock();
    /* Takeover the buffer */
    dataMsg = nlh;
    dataLen = NLMSG_PAYLOAD(dataMsg, 0);
	dataStart = static_cast<uint8_t *>(NLMSG_DATA(dataMsg));
	dataMutex.unlock();
	dataLeft.signal();
}
void parseBinaryNetLinkMessage(struct nlmsghdr *nlh)
{
	int len = nlh->nlmsg_len - sizeof(*nlh);
	struct ifinfomsg *ifi;

	if(sizeof(*ifi) > (size_t)len){
		printf("Got a short message\n");
		return ;
	}

	ifi = (struct  ifinfomsg*)NLMSG_DATA(nlh);
	if((ifi->ifi_flags & IFF_LOOPBACK) != 0){
		return ;
	}

	struct rtattr *rta = (struct rtattr*)
		((char*)ifi + NLMSG_ALIGN(sizeof(*ifi)));
	len = NLMSG_PAYLOAD(nlh,sizeof(*ifi));

	while(RTA_OK(rta,len)){
		switch(rta->rta_type){
			case IFLA_IFNAME:
			{
				char ifname[IFNAMSIZ];
				int  up;
				int id;
				snprintf(ifname,sizeof(ifname),"%s",
					(char*)RTA_DATA(rta));
				up = (ifi->ifi_flags & IFF_RUNNING)? 1 : 0;
				if (up && ((ifname[0] == 'p')&&(ifname[1] == 'p')&&
					(ifname[2] == 'p'))){
					printf("msg from:%s",ifname);
					sscanf(ifname+3,"%d",&id);
					if(nic_bitmap[id])
						break;
					start_capture(ifname);
					nic_bitmap[id] = 1;	
					printf("%s  %d\n",ifname,up);
				} 
				if (!up && ((ifname[0] == 'p')&&(ifname[1] == 'p')&&
                                        (ifname[2] == 'p'))){
					sscanf(ifname+3,"%d",(int*)&id);
					nic_bitmap[id] = 0;
					printf("%s %d\n",ifname,up);
				}
			}
		}

		rta = RTA_NEXT(rta,len);
	}

}
Ejemplo n.º 11
0
int sd_rtnl_message_rewind(sd_rtnl_message *m) {
        const NLType *type;
        unsigned i;
        int r;

        assert_return(m, -EINVAL);

        /* don't allow appending to message once parsed */
        if (!m->sealed)
                rtnl_message_seal(m);

        for (i = 1; i <= m->n_containers; i++) {
                free(m->rta_offset_tb[i]);
                m->rta_offset_tb[i] = NULL;
                m->rta_tb_size[i] = 0;
                m->container_type_system[i] = NULL;
        }

        m->n_containers = 0;

        if (m->rta_offset_tb[0]) {
                /* top-level attributes have already been parsed */
                return 0;
        }

        assert(m->hdr);

        r = type_system_get_type(NULL, &type, m->hdr->nlmsg_type);
        if (r < 0)
                return r;

        if (type->type == NLA_NESTED) {
                const NLTypeSystem *type_system = type->type_system;

                assert(type_system);

                m->container_type_system[0] = type_system;

                r = rtnl_message_parse(m,
                                       &m->rta_offset_tb[m->n_containers],
                                       &m->rta_tb_size[m->n_containers],
                                       type_system->max,
                                       (struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) +
                                                        NLMSG_ALIGN(type->size)),
                                       NLMSG_PAYLOAD(m->hdr, type->size));
                if (r < 0)
                        return r;
        }

        return 0;
}
Ejemplo n.º 12
0
int sd_netlink_message_rewind(sd_netlink_message *m) {
        const NLType *nl_type;
        uint16_t type;
        size_t size;
        unsigned i;
        int r;

        assert_return(m, -EINVAL);

        /* don't allow appending to message once parsed */
        if (!m->sealed)
                rtnl_message_seal(m);

        for (i = 1; i <= m->n_containers; i++)
                m->containers[i].attributes = mfree(m->containers[i].attributes);

        m->n_containers = 0;

        if (m->containers[0].attributes)
                /* top-level attributes have already been parsed */
                return 0;

        assert(m->hdr);

        r = type_system_get_type(&type_system_root, &nl_type, m->hdr->nlmsg_type);
        if (r < 0)
                return r;

        type = type_get_type(nl_type);
        size = type_get_size(nl_type);

        if (type == NETLINK_TYPE_NESTED) {
                const NLTypeSystem *type_system;

                type_get_type_system(nl_type, &type_system);

                m->containers[0].type_system = type_system;

                r = netlink_container_parse(m,
                                            &m->containers[m->n_containers],
                                            type_system_get_count(type_system),
                                            (struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) + NLMSG_ALIGN(size)),
                                            NLMSG_PAYLOAD(m->hdr, size));
                if (r < 0)
                        return r;
        }

        return 0;
}
Ejemplo n.º 13
0
/* return true if there is a known address with 'tentative' flag set */
static bool
virNetDevIPParseDadStatus(struct nlmsghdr *nlh, int len,
                          virSocketAddrPtr *addrs, size_t count)
{
    struct ifaddrmsg *ifaddrmsg_ptr;
    unsigned int ifaddrmsg_len;
    struct rtattr *rtattr_ptr;
    size_t i;
    struct in6_addr *addr;

    VIR_WARNINGS_NO_CAST_ALIGN
    for (; NLMSG_OK(nlh, len); nlh = NLMSG_NEXT(nlh, len)) {
        VIR_WARNINGS_RESET
        if (NLMSG_PAYLOAD(nlh, 0) < sizeof(struct ifaddrmsg)) {
            /* Message without payload is the last one. */
            break;
        }

        ifaddrmsg_ptr = (struct ifaddrmsg *)NLMSG_DATA(nlh);
        if (!(ifaddrmsg_ptr->ifa_flags & IFA_F_TENTATIVE)) {
            /* Not tentative: we are not interested in this entry. */
            continue;
        }

        ifaddrmsg_len = IFA_PAYLOAD(nlh);
        VIR_WARNINGS_NO_CAST_ALIGN
        rtattr_ptr = (struct rtattr *) IFA_RTA(ifaddrmsg_ptr);
        for (; RTA_OK(rtattr_ptr, ifaddrmsg_len);
            rtattr_ptr = RTA_NEXT(rtattr_ptr, ifaddrmsg_len)) {
            VIR_WARNINGS_RESET
            if (RTA_PAYLOAD(rtattr_ptr) != sizeof(struct in6_addr)) {
                /* No address: ignore. */
                continue;
            }

            /* We check only known addresses. */
            for (i = 0; i < count; i++) {
                addr = &addrs[i]->data.inet6.sin6_addr;
                if (!memcmp(addr, RTA_DATA(rtattr_ptr),
                            sizeof(struct in6_addr))) {
                    /* We found matching tentative address. */
                    return true;
                }
            }
        }
    }
    return false;
}
Ejemplo n.º 14
0
/*
 * parse traffic control message
 */
int parse_tcamsg(struct nlmsghdr *nlh)
{
    struct tcamsg *tcam;
    int tcam_len;
    struct rtattr *tcaa[TCAA_MAX+1];
    char msg[MAX_MSG_SIZE] = "";
    char *mp = msg;
    int log_opts = get_log_opts();

    /* debug nlmsghdr */
    if(log_opts & L_DEBUG)
        debug_nlmsg(0, nlh);

    /* get tcamsg */
    tcam_len = NLMSG_PAYLOAD(nlh, 0);
    if(tcam_len < sizeof(*tcam)) {
        rec_log("error: %s: length too short", __func__);
        return(1);
    }
    tcam = (struct tcamsg *)NLMSG_DATA(nlh);

    /* parse traffic control action message attributes */
    parse_tca(tcaa, nlh);

    /* debug tcamsg */
    if(log_opts & L_DEBUG)
        debug_tcamsg(0, tcam, tcaa, tcam_len);

    /* kind of message */
    switch(nlh->nlmsg_type) {
        case RTM_NEWACTION:
            mp = add_log(msg, mp, "tc action added: ");
            break;
        case RTM_DELACTION:
            mp = add_log(msg, mp, "tc action deleted: ");
            break;
        default:
            return(1);
    }

    if(tcaa[TCA_ACT_TAB])
        if(parse_tca_acts(msg, mp, tcaa[TCA_ACT_TAB]))
            return(1);

    return(0);
}
Ejemplo n.º 15
0
static int nfct_parse_ct(nfct_msg *ctmsg, struct nlmsghdr *nlh)
{
    struct nfgenmsg *nfmsg = (struct nfgenmsg *)NLMSG_DATA(nlh);
    conn_entry *e;
    struct nlattr *nla;
    int len;

    if(! instantiate(e))
        return 0;
    BZERO(e);
    e->l3num = nfmsg->nfgen_family;
    nla = (struct nlattr *)((char *)NLMSG_DATA(nlh) + NLMSG_ALIGN(sizeof(struct nfgenmsg)));
    len = NLMSG_PAYLOAD(nlh, sizeof(struct nfgenmsg));
    nla_parse(e->nla, CTA_MAX, nla, len);
    if(e->nla[CTA_STATUS])
        e->status = ntohl(nla_get_be32(e->nla[CTA_STATUS]));
    ctmsg->entry = e;
    return 0;
}
Ejemplo n.º 16
0
/*
 * For routers, this is called from dn_fib_dump, but for endnodes its
 * called directly from the rtnetlink dispatch table.
 */
int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb)
{
	struct dn_route *rt;
	int h, s_h;
	int idx, s_idx;

	if (NLMSG_PAYLOAD(cb->nlh, 0) < sizeof(struct rtmsg))
		return -EINVAL;
	if (!(((struct rtmsg *)NLMSG_DATA(cb->nlh))->rtm_flags&RTM_F_CLONED))
		return 0;

	s_h = cb->args[0];
	s_idx = idx = cb->args[1];
	for(h = 0; h <= dn_rt_hash_mask; h++) {
		if (h < s_h)
			continue;
		if (h > s_h)
			s_idx = 0;
		rcu_read_lock_bh();
		for(rt = rcu_dereference(dn_rt_hash_table[h].chain), idx = 0;
			rt;
			rt = rcu_dereference(rt->u.rt_next), idx++) {
			if (idx < s_idx)
				continue;
			skb->dst = dst_clone(&rt->u.dst);
			if (dn_rt_fill_info(skb, NETLINK_CB(cb->skb).pid,
					cb->nlh->nlmsg_seq, RTM_NEWROUTE, 
					1, NLM_F_MULTI) <= 0) {
				dst_release(xchg(&skb->dst, NULL));
				rcu_read_unlock_bh();
				goto done;
			}
			dst_release(xchg(&skb->dst, NULL));
		}
		rcu_read_unlock_bh();
	}

done:
	cb->args[0] = h;
	cb->args[1] = idx;
	return skb->len;
}
static int
link_netlink(struct nlmsghdr *nlm, const char *ifname)
{
	int len;
	struct rtattr *rta;
	struct ifinfomsg *ifi;
	char ifn[IF_NAMESIZE + 1];

	if (nlm->nlmsg_type != RTM_NEWLINK && nlm->nlmsg_type != RTM_DELLINK)
		return 0;
	len = nlm->nlmsg_len - sizeof(*nlm);
	if ((size_t)len < sizeof(*ifi)) {
		errno = EBADMSG;
		return -1;
	}
	ifi = NLMSG_DATA(nlm);
	if (ifi->ifi_flags & IFF_LOOPBACK)
		return 0;
	rta = (struct rtattr *) ((char *)ifi + NLMSG_ALIGN(sizeof(*ifi)));
	len = NLMSG_PAYLOAD(nlm, sizeof(*ifi));
	*ifn = '\0';
	while (RTA_OK(rta, len)) {
		switch (rta->rta_type) {
		case IFLA_WIRELESS:
			/* Ignore wireless messages */
			if (nlm->nlmsg_type == RTM_NEWLINK &&
			    ifi->ifi_change  == 0)
				return 0;
			break;
		case IFLA_IFNAME:
			strlcpy(ifn, RTA_DATA(rta), sizeof(ifn));
			break;
		}
		rta = RTA_NEXT(rta, len);
	}

	if (strncmp(ifname, ifn, sizeof(ifn)) == 0)
		return 1;
	return 0;
}
Ejemplo n.º 18
0
void nsexec(void)
{
	int pipenum;

	// If we don't have init pipe, then just return to the go routine,
	// we'll only have init pipe for start or exec
	pipenum = get_init_pipe();
	if (pipenum == -1) {
		return;
	}

	// Retrieve the netlink header
	struct nlmsghdr nl_msg_hdr;
	int		len;

	if ((len = read(pipenum, &nl_msg_hdr, NLMSG_HDRLEN)) != NLMSG_HDRLEN) {
		pr_perror("Invalid netlink header length %d", len);
		exit(1);
	}

	if (nl_msg_hdr.nlmsg_type == NLMSG_ERROR) {
		pr_perror("Failed to read netlink message");
		exit(1);
	}

	if (nl_msg_hdr.nlmsg_type != INIT_MSG) {
		pr_perror("Unexpected msg type %d", nl_msg_hdr.nlmsg_type);
		exit(1);
	}

	// Retrieve data
	int  nl_total_size = NLMSG_PAYLOAD(&nl_msg_hdr, 0);
	char data[nl_total_size];

	if ((len = read(pipenum, data, nl_total_size)) != nl_total_size) {
		pr_perror("Failed to read netlink payload, %d != %d", len,
			  nl_total_size);
		exit(1);
	}

	jmp_buf	env;
	int	syncpipe[2] = {-1, -1};
	struct	nsenter_config config = process_nl_attributes(pipenum,
						data, nl_total_size);

	// required clone_flags to be passed
	if (config.cloneflags == -1) {
		pr_perror("Missing clone_flags");
		exit(1);
	}
	// prepare sync pipe between parent and child. We need this to let the
	// child know that the parent has finished setting up
	if (pipe(syncpipe) != 0) {
		pr_perror("Failed to setup sync pipe between parent and child");
		exit(1);
	}

	if (setjmp(env) == 1) {
		// Child
		uint8_t s = 0;
		int	consolefd = config.consolefd;

		// close the writing side of pipe
		close(syncpipe[1]);

		// sync with parent
		if ((read(syncpipe[0], &s, 1) != 1) || (s != 1)) {
			pr_perror("Failed to read sync byte from parent");
			exit(1);
		}

		if (setsid() == -1) {
			pr_perror("setsid failed");
			exit(1);
		}

		if (setuid(0) == -1) {
			pr_perror("setuid failed");
			exit(1);
		}

		if (setgid(0) == -1) {
			pr_perror("setgid failed");
			exit(1);
		}
    
		if (setgroups(0, NULL) == -1) {
			pr_perror("setgroups failed");
			exit(1);
		}

		if (consolefd != -1) {
			if (ioctl(consolefd, TIOCSCTTY, 0) == -1) {
				pr_perror("ioctl TIOCSCTTY failed");
				exit(1);
			}
			if (dup3(consolefd, STDIN_FILENO, 0) != STDIN_FILENO) {
				pr_perror("Failed to dup stdin");
				exit(1);
			}
			if (dup3(consolefd, STDOUT_FILENO, 0) != STDOUT_FILENO) {
				pr_perror("Failed to dup stdout");
				exit(1);
			}
			if (dup3(consolefd, STDERR_FILENO, 0) != STDERR_FILENO) {
				pr_perror("Failed to dup stderr");
				exit(1);
			}
		}

		// Finish executing, let the Go runtime take over.
		return;
	}

	// Parent
	start_child(pipenum, &env, syncpipe, &config);
}
static gboolean
read_netlink_messages (GSocket      *socket,
                       GIOCondition  condition,
                       gpointer      user_data)
{
  GNetworkMonitorNetlink *nl = user_data;
  GInputVector iv;
  gssize len;
  GSocketControlMessage **cmsgs = NULL;
  gint num_cmsgs = 0, i, flags;
  GError *error = NULL;
  GCredentials *creds;
  uid_t sender;
  struct nlmsghdr *msg;
  struct rtmsg *rtmsg;
  struct rtattr *attr;
  gsize attrlen;
  guint8 *dest, *gateway;
  gboolean retval = TRUE;

  iv.buffer = NULL;
  iv.size = 0;

  flags = MSG_PEEK | MSG_TRUNC;
  len = g_socket_receive_message (nl->priv->sock, NULL, &iv, 1,
                                  NULL, NULL, &flags, NULL, &error);
  if (len < 0)
    {
      g_warning ("Error on netlink socket: %s", error->message);
      g_error_free (error);
      if (nl->priv->dump_networks)
        finish_dump (nl);
      return FALSE;
    }

  iv.buffer = g_malloc (len);
  iv.size = len;
  len = g_socket_receive_message (nl->priv->sock, NULL, &iv, 1,
                                  &cmsgs, &num_cmsgs, NULL, NULL, &error);
  if (len < 0)
    {
      g_warning ("Error on netlink socket: %s", error->message);
      g_error_free (error);
      if (nl->priv->dump_networks)
        finish_dump (nl);
      return FALSE;
    }

  if (num_cmsgs != 1 || !G_IS_UNIX_CREDENTIALS_MESSAGE (cmsgs[0]))
    goto done;

  creds = g_unix_credentials_message_get_credentials (G_UNIX_CREDENTIALS_MESSAGE (cmsgs[0]));
  sender = g_credentials_get_unix_user (creds, NULL);
  if (sender != 0)
    goto done;

  msg = (struct nlmsghdr *) iv.buffer;
  for (; len > 0; msg = NLMSG_NEXT (msg, len))
    {
      if (!NLMSG_OK (msg, (size_t) len))
        {
          g_warning ("netlink message was truncated; shouldn't happen...");
          retval = FALSE;
          goto done;
        }

      switch (msg->nlmsg_type)
        {
        case RTM_NEWROUTE:
        case RTM_DELROUTE:
          rtmsg = NLMSG_DATA (msg);

          if (rtmsg->rtm_family != AF_INET && rtmsg->rtm_family != AF_INET6)
            continue;
          if (rtmsg->rtm_type == RTN_UNREACHABLE)
            continue;

          attrlen = NLMSG_PAYLOAD (msg, sizeof (struct rtmsg));
          attr = RTM_RTA (rtmsg);
          dest = gateway = NULL;
          while (RTA_OK (attr, attrlen))
            {
              if (attr->rta_type == RTA_DST)
                dest = RTA_DATA (attr);
              else if (attr->rta_type == RTA_GATEWAY)
                gateway = RTA_DATA (attr);
              attr = RTA_NEXT (attr, attrlen);
            }

          if (dest || gateway)
            {
              if (msg->nlmsg_type == RTM_NEWROUTE)
                add_network (nl, rtmsg->rtm_family, rtmsg->rtm_dst_len, dest, gateway);
              else
                remove_network (nl, rtmsg->rtm_family, rtmsg->rtm_dst_len, dest, gateway);
              queue_request_dump (nl);
            }
          break;

        case NLMSG_DONE:
          finish_dump (nl);
          goto done;

        case NLMSG_ERROR:
          {
            struct nlmsgerr *e = NLMSG_DATA (msg);

            g_warning ("netlink error: %s", g_strerror (-e->error));
          }
          retval = FALSE;
          goto done;

        default:
          g_warning ("unexpected netlink message %d", msg->nlmsg_type);
          retval = FALSE;
          goto done;
        }
    }

 done:
  for (i = 0; i < num_cmsgs; i++)
    g_object_unref (cmsgs[i]);
  g_free (cmsgs);

  g_free (iv.buffer);

  if (!retval && nl->priv->dump_networks)
    finish_dump (nl);
  return retval;
}
Ejemplo n.º 20
0
static void
get_if_prefix(struct nlmsghdr *nlm, int nlm_len, int request,
	      struct dhcp6_if *ifp)
{
	struct rtmsg *rtm = (struct rtmsg *)NLMSG_DATA(nlm);
	struct rtattr *rta;
	size_t rtasize, rtapayload;
	void *rtadata;
	struct ra_info *rainfo;
	char addr[64];

	if (rtm->rtm_family != AF_INET6 || nlm->nlmsg_type != request)
		return;

	if (!(rtm->rtm_flags & RTM_F_PREFIX)) 
		return;

	rtasize = NLMSG_PAYLOAD(nlm, nlm_len) - NLMSG_ALIGN(sizeof(*rtm));
	rta = (struct rtattr *) (((char *) NLMSG_DATA(nlm)) +
	      NLMSG_ALIGN(sizeof(*rtm)));
	if (!RTA_OK(rta, rtasize))
		return;
	rtadata = RTA_DATA(rta);
	rtapayload = RTA_PAYLOAD(rta);
	switch(rta->rta_type) {
	case RTA_OIF:
		break;
	default:
		break; 
	}
	switch (rta->rta_type) {	
	case RTA_DST:
		rainfo = (struct ra_info *)malloc(sizeof(*rainfo));
		if (rainfo == NULL)
			return;
		memset(rainfo, 0, sizeof(rainfo));
		memcpy(&(rainfo->prefix), (struct in6_addr *)rtadata, 
		       sizeof(struct in6_addr));
		rainfo->plen = rtm->rtm_dst_len;
		if (ifp->ralist == NULL) {
			ifp->ralist = rainfo;
			rainfo->next = NULL;
		} else {
			struct ra_info *ra, *ra_prev;
			ra_prev = ifp->ralist;
			for (ra = ifp->ralist; ra; ra = ra->next) {
				if (rainfo->plen >= ra->plen) {
					if (ra_prev == ra) {
						ifp->ralist = rainfo;
						rainfo->next = ra;
					} else {
						ra_prev->next = rainfo;
						rainfo->next = ra;
					}
					break;
				} else {
					if (ra->next == NULL) {
						ra->next = rainfo;
						rainfo->next = NULL;
						break;
					} else {
						ra_prev = ra;
						continue;
					}
				}
			}
		}
		inet_ntop(AF_INET6, &(rainfo->prefix), addr, INET6_ADDRSTRLEN);
		dprintf(LOG_DEBUG, "get prefix address %s", addr);
		dprintf(LOG_DEBUG, "get prefix plen %d",rtm->rtm_dst_len);
		break;
	case RTA_CACHEINFO:
		dprintf(LOG_DEBUG, "prefix route life time is %d\n",
		      ((struct rta_cacheinfo *)rtadata)->rta_expires);
		break;
	default:
		break;
	}
	return;
}
Ejemplo n.º 21
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;
}
Ejemplo n.º 22
0
static int interpretLink(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList)
{
    struct ifinfomsg *l_info = (struct ifinfomsg *)NLMSG_DATA(p_hdr);

    size_t l_nameSize = 0;
    size_t l_addrSize = 0;
    size_t l_dataSize = 0;

    size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg));
    struct rtattr *l_rta;
    for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
    {
        size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
        switch(l_rta->rta_type)
        {
        case IFLA_ADDRESS:
        case IFLA_BROADCAST:
            l_addrSize += NLMSG_ALIGN(calcAddrLen(AF_PACKET, l_rtaDataSize));
            break;
        case IFLA_IFNAME:
            l_nameSize += NLMSG_ALIGN(l_rtaSize + 1);
            break;
        case IFLA_STATS:
            l_dataSize += NLMSG_ALIGN(l_rtaSize);
            break;
        default:
            break;
        }
    }

    struct ifaddrs *l_entry = malloc(sizeof(struct ifaddrs) + sizeof(int) + l_nameSize + l_addrSize + l_dataSize);
    if (l_entry == NULL)
    {
        return -1;
    }
    memset(l_entry, 0, sizeof(struct ifaddrs));
    l_entry->ifa_name = "";

    char *l_index = ((char *)l_entry) + sizeof(struct ifaddrs);
    char *l_name = l_index + sizeof(int);
    char *l_addr = l_name + l_nameSize;
    char *l_data = l_addr + l_addrSize;

    // save the interface index so we can look it up when handling the addresses.
    memcpy(l_index, &l_info->ifi_index, sizeof(int));

    l_entry->ifa_flags = l_info->ifi_flags;

    l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg));
    for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
    {
        void *l_rtaData = RTA_DATA(l_rta);
        size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
        switch(l_rta->rta_type)
        {
        case IFLA_ADDRESS:
        case IFLA_BROADCAST:
        {
            size_t l_addrLen = calcAddrLen(AF_PACKET, l_rtaDataSize);
            makeSockaddr(AF_PACKET, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize);
            ((struct sockaddr_ll *)l_addr)->sll_ifindex = l_info->ifi_index;
            ((struct sockaddr_ll *)l_addr)->sll_hatype = l_info->ifi_type;
            if(l_rta->rta_type == IFLA_ADDRESS)
            {
                l_entry->ifa_addr = (struct sockaddr *)l_addr;
            }
            else
            {
                l_entry->ifa_broadaddr = (struct sockaddr *)l_addr;
            }
            l_addr += NLMSG_ALIGN(l_addrLen);
            break;
        }
        case IFLA_IFNAME:
            strncpy(l_name, l_rtaData, l_rtaDataSize);
            l_name[l_rtaDataSize] = '\0';
            l_entry->ifa_name = l_name;
            break;
        case IFLA_STATS:
            memcpy(l_data, l_rtaData, l_rtaDataSize);
            l_entry->ifa_data = l_data;
            break;
        default:
            break;
        }
    }

    addToEnd(p_resultList, l_entry);
    return 0;
}
Ejemplo n.º 23
0
static int interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList, int p_numLinks)
{
    struct ifaddrmsg *l_info = (struct ifaddrmsg *)NLMSG_DATA(p_hdr);
    struct ifaddrs *l_interface = findInterface(l_info->ifa_index, p_resultList, p_numLinks);

    if(l_info->ifa_family == AF_PACKET)
    {
        return 0;
    }

    size_t l_nameSize = 0;
    size_t l_addrSize = 0;

    int l_addedNetmask = 0;

    size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg));
    struct rtattr *l_rta;
    for(l_rta = IFA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
    {
        size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);

        switch(l_rta->rta_type)
        {
        case IFA_ADDRESS:
        case IFA_LOCAL:
            if((l_info->ifa_family == AF_INET || l_info->ifa_family == AF_INET6) && !l_addedNetmask)
            {   // make room for netmask
                l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
                l_addedNetmask = 1;
            }
        case IFA_BROADCAST:
            l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
            break;
        case IFA_LABEL:
            l_nameSize += NLMSG_ALIGN(l_rtaSize + 1);
            break;
        default:
            break;
        }
    }

    struct ifaddrs *l_entry = malloc(sizeof(struct ifaddrs) + l_nameSize + l_addrSize);
    if (l_entry == NULL)
    {
        return -1;
    }
    memset(l_entry, 0, sizeof(struct ifaddrs));
    l_entry->ifa_name = (l_interface ? l_interface->ifa_name : "");

    char *l_name = ((char *)l_entry) + sizeof(struct ifaddrs);
    char *l_addr = l_name + l_nameSize;

    l_entry->ifa_flags = l_info->ifa_flags;
    if(l_interface)
    {
        l_entry->ifa_flags |= l_interface->ifa_flags;
    }

    l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg));
    for(l_rta = IFA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
    {
        void *l_rtaData = RTA_DATA(l_rta);
        size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
        switch(l_rta->rta_type)
        {
        case IFA_ADDRESS:
        case IFA_BROADCAST:
        case IFA_LOCAL:
        {
            size_t l_addrLen = calcAddrLen(l_info->ifa_family, l_rtaDataSize);
            makeSockaddr(l_info->ifa_family, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize);
            if(l_info->ifa_family == AF_INET6)
            {
                if(IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)l_rtaData) || IN6_IS_ADDR_MC_LINKLOCAL((struct in6_addr *)l_rtaData))
                {
                    ((struct sockaddr_in6 *)l_addr)->sin6_scope_id = l_info->ifa_index;
                }
            }

            if(l_rta->rta_type == IFA_ADDRESS)
            {   // apparently in a point-to-point network IFA_ADDRESS contains the dest address and IFA_LOCAL contains the local address
                if(l_entry->ifa_addr)
                {
                    l_entry->ifa_dstaddr = (struct sockaddr *)l_addr;
                }
                else
                {
                    l_entry->ifa_addr = (struct sockaddr *)l_addr;
                }
            }
            else if(l_rta->rta_type == IFA_LOCAL)
            {
                if(l_entry->ifa_addr)
                {
                    l_entry->ifa_dstaddr = l_entry->ifa_addr;
                }
                l_entry->ifa_addr = (struct sockaddr *)l_addr;
            }
            else
            {
                l_entry->ifa_broadaddr = (struct sockaddr *)l_addr;
            }
            l_addr += NLMSG_ALIGN(l_addrLen);
            break;
        }
        case IFA_LABEL:
            strncpy(l_name, l_rtaData, l_rtaDataSize);
            l_name[l_rtaDataSize] = '\0';
            l_entry->ifa_name = l_name;
            break;
        default:
            break;
        }
    }

    if(l_entry->ifa_addr && (l_entry->ifa_addr->sa_family == AF_INET || l_entry->ifa_addr->sa_family == AF_INET6))
    {
        unsigned l_maxPrefix = (l_entry->ifa_addr->sa_family == AF_INET ? 32 : 128);
        unsigned l_prefix = (l_info->ifa_prefixlen > l_maxPrefix ? l_maxPrefix : l_info->ifa_prefixlen);
        char l_mask[16] = {0};
        unsigned i;
        for(i=0; i<(l_prefix/8); ++i)
        {
            l_mask[i] = 0xff;
        }
        if(l_prefix % 8)
        {
            l_mask[i] = 0xff << (8 - (l_prefix % 8));
        }

        makeSockaddr(l_entry->ifa_addr->sa_family, (struct sockaddr *)l_addr, l_mask, l_maxPrefix / 8);
        l_entry->ifa_netmask = (struct sockaddr *)l_addr;
    }

    addToEnd(p_resultList, l_entry);
    return 0;
}
Ejemplo n.º 24
0
static int process_nlmsg(struct nlmsghdr *n) {
    assert(n);

    if (n->nlmsg_type == RTM_NEWLINK || n->nlmsg_type == RTM_DELLINK) {
        /* A link appeared or was removed */

        struct ifinfomsg *ifi;
        ifi = NLMSG_DATA(n);

        if (ifi->ifi_family != AF_UNSPEC || (int) ifi->ifi_index != ifindex)
            return 0;
        
        if (n->nlmsg_type == RTM_DELLINK) {
            daemon_log(LOG_ERR, "Interface vanished.");
            return -1;
        }

        assert(n->nlmsg_type == RTM_NEWLINK);
        
        if ((ifi->ifi_flags & IFF_LOOPBACK) ||
            (ifi->ifi_flags & IFF_NOARP) ||
            ifi->ifi_type != ARPHRD_ETHER) {
            daemon_log(LOG_ERR, "Interface not suitable.");
            return -1;
        }

    } else if (n->nlmsg_type == RTM_NEWADDR || n->nlmsg_type == RTM_DELADDR) {

        /* An address was added or removed */

        struct rtattr *a = NULL;
        struct ifaddrmsg *ifa;
        int l;
        uint32_t address = 0;
        Address *i;
        
        ifa = NLMSG_DATA(n);

        if (ifa->ifa_family != AF_INET || (int) ifa->ifa_index != ifindex)
            return 0;

        l = NLMSG_PAYLOAD(n, sizeof(*ifa));
        a = IFLA_RTA(ifa);

        while(RTA_OK(a, l)) {

            switch(a->rta_type) {
                case IFA_LOCAL:
                case IFA_ADDRESS:
                    assert(RTA_PAYLOAD(a) == 4);
                    memcpy(&address, RTA_DATA(a), sizeof(uint32_t));
                    break;
            }
            
            a = RTA_NEXT(a, l);
        }

        if (!address || is_ll_address(address))
            return 0;

        for (i = addresses; i; i = i->addresses_next)
            if (i->address == address)
                break;

        if (n->nlmsg_type == RTM_DELADDR && i) {
            AVAHI_LLIST_REMOVE(Address, addresses, addresses, i);
            avahi_free(i);
        } if (n->nlmsg_type == RTM_NEWADDR && !i) {
            i = avahi_new(Address, 1);
            i->address = address;
            AVAHI_LLIST_PREPEND(Address, addresses, addresses, i);
        }
    }

    return 0;
}
Ejemplo n.º 25
0
// Detect an IPV6-address currently assigned to the given interface
ssize_t relayd_get_interface_addresses(int ifindex,
		struct relayd_ipaddr *addrs, size_t cnt)
{
	struct {
		struct nlmsghdr nhm;
		struct ifaddrmsg ifa;
	} req = {{sizeof(req), RTM_GETADDR, NLM_F_REQUEST | NLM_F_DUMP,
			++rtnl_seq, 0}, {AF_INET6, 0, 0, 0, ifindex}};
	if (send(rtnl_socket, &req, sizeof(req), 0) < (ssize_t)sizeof(req))
		return 0;

	uint8_t buf[8192];
	ssize_t len = 0, ret = 0;

	for (struct nlmsghdr *nhm = NULL; ; nhm = NLMSG_NEXT(nhm, len)) {
		while (len < 0 || !NLMSG_OK(nhm, (size_t)len)) {
			len = recv(rtnl_socket, buf, sizeof(buf), 0);
			nhm = (struct nlmsghdr*)buf;
			if (len < 0 || !NLMSG_OK(nhm, (size_t)len)) {
				if (errno == EINTR)
					continue;
				else
					return ret;
			}
		}

		if (nhm->nlmsg_type != RTM_NEWADDR)
			break;

		// Skip address but keep clearing socket buffer
		if (ret >= (ssize_t)cnt)
			continue;

		struct ifaddrmsg *ifa = NLMSG_DATA(nhm);
		if (ifa->ifa_scope != RT_SCOPE_UNIVERSE ||
				ifa->ifa_index != (unsigned)ifindex)
			continue;

		struct rtattr *rta = (struct rtattr*)&ifa[1];
		size_t alen = NLMSG_PAYLOAD(nhm, sizeof(*ifa));
		memset(&addrs[ret], 0, sizeof(addrs[ret]));
		addrs[ret].prefix = ifa->ifa_prefixlen;

		while (RTA_OK(rta, alen)) {
			if (rta->rta_type == IFA_ADDRESS) {
				memcpy(&addrs[ret].addr, RTA_DATA(rta),
						sizeof(struct in6_addr));
			} else if (rta->rta_type == IFA_CACHEINFO) {
				struct ifa_cacheinfo *ifc = RTA_DATA(rta);
				addrs[ret].preferred = ifc->ifa_prefered;
				addrs[ret].valid = ifc->ifa_valid;
			}

			rta = RTA_NEXT(rta, alen);
		}

		if (ifa->ifa_flags & IFA_F_DEPRECATED)
			addrs[ret].preferred = 0;

		++ret;
	}

	return ret;
}
Ejemplo n.º 26
0
/*
 * parse traffic control filter messages
 */
int parse_tcmsg_filter(struct nlmsghdr *nlh)
{
    struct tcmsg *tcm;
    int tcm_len;
    struct rtattr *tca[__TCA_MAX];
    char msg[MAX_MSG_SIZE] = "";
    char *mp = msg;
    char ifname[IFNAMSIZ];
    char handle[MAX_STR_SIZE] = "";
    char kind[IFNAMSIZ] = "(unknown)";
    char proto[MAX_STR_SIZE];
    int log_opts = get_log_opts();

    /* debug nlmsghdr */
    if(log_opts & L_DEBUG)
        debug_nlmsg(0, nlh);

    /* get tcmsg */
    tcm_len = NLMSG_PAYLOAD(nlh, 0);
    if(tcm_len < sizeof(*tcm)) {
        rec_log("error: %s: tcmsg: length too short", __func__);
        return(1);
    }
    tcm = (struct tcmsg *)NLMSG_DATA(nlh);

    /* parse traffic control message attributes */
    parse_tc(tca, nlh);

    /* debug tcmsg */
    if(log_opts & L_DEBUG)
        debug_tcmsg(0, nlh, tcm, tca, tcm_len);

    /* kind of message */
    switch(nlh->nlmsg_type) {
        case RTM_NEWTFILTER:
            mp = add_log(msg, mp, "tc filter added: ");
            break;
        case RTM_DELTFILTER:
            mp = add_log(msg, mp, "tc filter deleted: ");
            break;
        default:
            rec_log("error: %s: nlmsg_type: unknown message", __func__);
            return(1);
    }

    /* get interface name */
    if_indextoname_from_lists(tcm->tcm_ifindex, ifname);

    mp = add_log(msg, mp, "interface=%s ", ifname); 

    /* get qdisc kind */
    if(tca[TCA_KIND])
        strncpy(kind, (char *)RTA_DATA(tca[TCA_KIND]), sizeof(kind));

    /* get filter handle */
    if(!strncmp(kind, "u32", sizeof(kind)))
        parse_u32_handle(handle, sizeof(handle), tcm->tcm_handle);
    else
        snprintf(handle, sizeof(handle), "0x%x", tcm->tcm_handle);

    mp = add_log(msg, mp, "handle=%s ", handle);

    /* get priority */
    mp = add_log(msg, mp, "priority=%u ", TC_H_MAJ(tcm->tcm_info)>>16);

    /* get priority */
    strncpy(proto, conv_eth_p(ntohs(TC_H_MIN(tcm->tcm_info)), 0), sizeof(proto));
    if(strlen(proto))
        mp = add_log(msg, mp, "protocol=%s ", proto);
    else
        mp = add_log(msg, mp, "protocol=0x%04x ", ntohs(TC_H_MIN(tcm->tcm_info)));

    /* get filter options */
    mp = add_log(msg, mp, "filter=%s ", kind);

    if(tca[TCA_OPTIONS]) {
        if(!strncmp(kind, "u32", sizeof(kind))) {
            if(parse_tca_options_u32(msg, &mp, tca[TCA_OPTIONS]))
                return(1);
            return(0);
        } else if(!strncmp(kind, "rsvp", sizeof(kind))) {
            if(parse_tca_options_rsvp(msg, &mp, tcm, tca[TCA_OPTIONS]))
                return(1);
            return(0);
        } else if(!strncmp(kind, "route", sizeof(kind))) {
            if(parse_tca_options_route(msg, &mp, tca[TCA_OPTIONS]))
                return(1);
            return(0);
        } else if(!strncmp(kind, "fw", sizeof(kind))) {
            if(parse_tca_options_fw(msg, &mp, tca[TCA_OPTIONS]))
                return(1);
            return(0);
        } else if(!strncmp(kind, "tcindex", sizeof(kind))) {
            if(parse_tca_options_tcindex(msg, &mp, tca[TCA_OPTIONS]))
                return(1);
            return(0);
#if HAVE_DECL_TCA_FLOW_UNSPEC
        } else if(!strncmp(kind, "flow", sizeof(kind))) {
            if(parse_tca_options_flow(msg, &mp, tca[TCA_OPTIONS]))
                return(1);
            return(0);
#endif
        } else if(!strncmp(kind, "basic", sizeof(kind))) {
            if(parse_tca_options_basic(msg, &mp, tca[TCA_OPTIONS]))
                return(1);
            return(0);
#if HAVE_DECL_TCA_CGROUP_UNSPEC
        } else if(!strncmp(kind, "cgroup", sizeof(kind))) {
            if(parse_tca_options_cgroup(msg, &mp, tca[TCA_OPTIONS]))
                return(1);
            return(0);
#endif
        }
    }

    rec_log("%s", msg);

    return(0);
}
/**
 *
 * void nl_data_ready(struct sk_buff *skb)
 *
 * This function is automatically called when the kernel receives a datagram on the corresponding netlink socket.
 */
void nl_data_ready(struct sk_buff *skb) {

	static int message_counter=0;
	message_counter++;
	struct nlmsghdr *nlh;
	u_char *buffer; // Pointer to data in payload
	u_char *buf;
//	strcat(buffer, "LOLOLOLOLOLO");
	int len; // Payload length
	int commandValueLength;
	u_char *commandValue;
	int pid; // pid of sending process

	struct nl_userspace80211_to_stub80211_msg *messageToParse;
	u_int reply_call; // a number corresponding to the type of socketcall this packet is in response to

	PRINT_DEBUG("Entered: skb=%p", skb);

	if (skb == NULL) {
		PRINT_DEBUG("Exiting: skb NULL \n");
		return;
	}
	nlh = (struct nlmsghdr *) skb->data;
	pid = nlh->nlmsg_pid; // get pid from the header

	// Get a pointer to the start of the data in the buffer and the buffer (payload) length
	buf = (u_char *) (NLMSG_DATA(nlh));
	len = NLMSG_PAYLOAD(nlh, 0);

	PRINT_DEBUG("Core Process ID nl_pid=%d,Payload Length  nl_len=%d", pid, len);

	// **** Remember the LKM must be up first, then the daemon,
	// but the daemon must make contact before any applications try to use socket()

	if (pid == -1) { // if the socket daemon hasn't made contact before
		// Print what we received
		PRINT_DEBUG("No msg pID, received='%p'", buf);
	} else {
	/**	if (len >= sizeof(struct nl_FINS_to_stub80211)) {
			hdr = (struct nl_FINS_to_stub80211 *) buf;
			len -= sizeof(struct nl_FINS_to_stub80211);
	*/
		if (len >= sizeof(struct nl_userspace80211_to_stub80211_msg )) {
			messageToParse = (struct nl_userspace80211_to_stub80211_msg *) buf;

			commandValueLength = len - sizeof (struct nl_userspace80211_to_stub80211_msg);
			if (messageToParse->commandValueLength != messageToParse->commandValueLength )
				PRINT_ERROR("THIS IS FATAL PROBLEM. length calcualted, does not equal"
						"length in the structure");

			PRINT_DEBUG("Received Message number = %d  call_type=%d, call_valueLength=%d, call_valuePointer=%c",
			message_counter,messageToParse->command_type, messageToParse->commandValueLength, messageToParse->value);

			if ( (messageToParse->commandValueLength ==0) &&
					(messageToParse->commandValueLength == messageToParse->commandValueLength ))
			{
				switch (messageToParse->command_type)

				{

				case STUB80211_CMD_SPECS:
					PRINT_DEBUG("STUB80211_CMD_SPECS:");
					break;
				case STUB80211_CMD_GETRATE:
					PRINT_DEBUG("STUB80211_CMD_GETRATE:");

					break;

				case STUB80211_CMD_SETRATE:
					PRINT_DEBUG("STUB80211_CMD_SETRATE::");
					break;

				case STUB80211_CMD_GETTXPOWER:
					PRINT_DEBUG("STUB80211_CMD_GETTXPOWER:::");
					break;

				case STUB80211_CMD_SETTXPOWER:
					PRINT_DEBUG("STUB80211_CMD_SETTXPOWER:::");
					break;

				case STUB80211_CMD_GETCW:
					PRINT_DEBUG("STUB80211_CMD_GETCW:::");

					break;

				case STUB80211_CMD_SETCW:
					PRINT_DEBUG("STUB80211_CMD_SETCW:::");

					break;

				case STUB80211_CMD_GETCWMIN:
					PRINT_DEBUG("STUB80211_CMD_GETCWMIN:::");
					break;

				case STUB80211_CMD_SETCWMIN:
					PRINT_DEBUG("STUB80211_CMD_SETCWMIN:::");
					break;

				case STUB80211_CMD_GETCWMAX:
					PRINT_DEBUG("STUB80211_CMD_GETCWMAX:::");
					break;

				case STUB80211_CMD_SETCWMAX:
					PRINT_DEBUG("STUB80211_CMD_SETCWMAX:::");
					break;

				case STUB80211_CMD_GETRSS:
					PRINT_DEBUG("STUB80211_CMD_GETRSS:::");
					break;
				case STUB80211_CMD_GETSTAT:
					PRINT_DEBUG("STUB80211_CMD_GETSTAT:::");
					struct ieee80211_low_level_stats toBeCopied;
					toBeCopied =
					break;





				default:
					PRINT_DEBUG("Command type is not found");

				}


			}
			else if (messageToParse->commandValueLength !=0)
			{
				PRINT_DEBUG("commandValueLength is not zero");
				commandValue = (u_char *) kmalloc(commandValueLength , GFP_KERNEL);
				if (commandValue == NULL) {
					PRINT_ERROR("buffer allocation error");
					return;
				}

				memcpy(commandValue, messageToParse->value, commandValueLength);

			}
			else
			{
				PRINT_DEBUG("\nERROR- should not enter here ever");


			}
			/**
			 * In this segment of code , we parse the message received from the userspace:
			 * According to the list of commands defined between the stub80211 LKM and
			 * the stub80211 userspace thread
			 *
			 */


		} //end of IF
/*
 * Parse a binary message from a NETLINK_ROUTE netlink socket.
 */
bool NetlinkEvent::parseBinaryNetlinkMessage(char *buffer, int size) {
    const struct nlmsghdr *nh;

    for (nh = (struct nlmsghdr *) buffer;
         NLMSG_OK(nh, (unsigned) size) && (nh->nlmsg_type != NLMSG_DONE);
         nh = NLMSG_NEXT(nh, size)) {

        if (nh->nlmsg_type == RTM_NEWLINK) {
            int len = nh->nlmsg_len - sizeof(*nh);
            struct ifinfomsg *ifi;

            if (sizeof(*ifi) > (size_t) len) {
                SLOGE("Got a short RTM_NEWLINK message\n");
                continue;
            }

            ifi = (ifinfomsg *)NLMSG_DATA(nh);
            if ((ifi->ifi_flags & IFF_LOOPBACK) != 0) {
                continue;
            }

            struct rtattr *rta = (struct rtattr *)
              ((char *) ifi + NLMSG_ALIGN(sizeof(*ifi)));
            len = NLMSG_PAYLOAD(nh, sizeof(*ifi));

            while(RTA_OK(rta, len)) {
                switch(rta->rta_type) {
                case IFLA_IFNAME:
                    char buffer[16 + IFNAMSIZ];
                    snprintf(buffer, sizeof(buffer), "INTERFACE=%s",
                             (char *) RTA_DATA(rta));
                    mParams[0] = strdup(buffer);
                    mAction = (ifi->ifi_flags & IFF_LOWER_UP) ?
                      NlActionLinkUp : NlActionLinkDown;
                    mSubsystem = strdup("net");
                    break;
                }

                rta = RTA_NEXT(rta, len);
            }

        } else if (nh->nlmsg_type == QLOG_NL_EVENT) {
            char *devname;
            ulog_packet_msg_t *pm;
            size_t len = nh->nlmsg_len - sizeof(*nh);
            if (sizeof(*pm) > len) {
                SLOGE("Got a short QLOG message\n");
                continue;
            }
            pm = (ulog_packet_msg_t *)NLMSG_DATA(nh);
            devname = pm->indev_name[0] ? pm->indev_name : pm->outdev_name;
            asprintf(&mParams[0], "ALERT_NAME=%s", pm->prefix);
            asprintf(&mParams[1], "INTERFACE=%s", devname);
            mSubsystem = strdup("qlog");
            mAction = NlActionChange;

        } else if (nh->nlmsg_type == RTM_NEWADDR ||
                   nh->nlmsg_type == RTM_DELADDR) {
            int len = nh->nlmsg_len - sizeof(*nh);
            struct ifaddrmsg *ifa;

            if (sizeof(*ifa) > (size_t) len) {
                SLOGE("Got a short RTM_xxxADDR message\n");
                continue;
            }

            ifa = (ifaddrmsg *)NLMSG_DATA(nh);
            size_t rtasize = IFA_PAYLOAD(nh);
            if (!parseIfAddrMessage(nh->nlmsg_type, ifa, rtasize)) {
                continue;
            }

        } else if (nh->nlmsg_type == RTM_NEWNDUSEROPT) {
            int len = nh->nlmsg_len - sizeof(*nh);
            struct nduseroptmsg *ndmsg = (struct nduseroptmsg *) NLMSG_DATA(nh);

            if (sizeof(*ndmsg) > (size_t) len) {
                SLOGE("Got a short RTM_NEWNDUSEROPT message\n");
                continue;
            }

            size_t optsize = NLMSG_PAYLOAD(nh, sizeof(*ndmsg));
            if (!parseNdUserOptMessage(ndmsg, optsize)) {
                continue;
            }


        } else {
                SLOGD("Unexpected netlink message. type=0x%x\n",
                      nh->nlmsg_type);
        }
    }

    return true;
}
Ejemplo n.º 29
0
int print_netconf(const struct sockaddr_nl *who, struct rtnl_ctrl_data *ctrl,
		  struct nlmsghdr *n, void *arg)
{
	FILE *fp = (FILE *)arg;
	struct netconfmsg *ncm = NLMSG_DATA(n);
	int len = n->nlmsg_len;
	struct rtattr *tb[NETCONFA_MAX+1];
	int ifindex = 0;

	if (n->nlmsg_type == NLMSG_ERROR)
		return -1;
	if (n->nlmsg_type != RTM_NEWNETCONF) {
		fprintf(stderr, "Not RTM_NEWNETCONF: %08x %08x %08x\n",
			n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);

		return -1;
	}
	len -= NLMSG_SPACE(sizeof(*ncm));
	if (len < 0) {
		fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
		return -1;
	}

	if (filter.family && filter.family != ncm->ncm_family)
		return 0;

	parse_rtattr(tb, NETCONFA_MAX, netconf_rta(ncm),
		     NLMSG_PAYLOAD(n, sizeof(*ncm)));

	if (tb[NETCONFA_IFINDEX])
		ifindex = rta_getattr_u32(tb[NETCONFA_IFINDEX]);

	if (filter.ifindex && filter.ifindex != ifindex)
		return 0;

	switch (ncm->ncm_family) {
	case AF_INET:
		fprintf(fp, "ipv4 ");
		break;
	case AF_INET6:
		fprintf(fp, "ipv6 ");
		break;
	case AF_MPLS:
		fprintf(fp, "mpls ");
		break;
	default:
		fprintf(fp, "unknown ");
		break;
	}

	if (tb[NETCONFA_IFINDEX]) {
		switch (ifindex) {
		case NETCONFA_IFINDEX_ALL:
			fprintf(fp, "all ");
			break;
		case NETCONFA_IFINDEX_DEFAULT:
			fprintf(fp, "default ");
			break;
		default:
			fprintf(fp, "dev %s ", ll_index_to_name(ifindex));
			break;
		}
	}

	if (tb[NETCONFA_FORWARDING])
		print_onoff(fp, "forwarding",
				rta_getattr_u32(tb[NETCONFA_FORWARDING]));
	if (tb[NETCONFA_RP_FILTER]) {
		__u32 rp_filter = rta_getattr_u32(tb[NETCONFA_RP_FILTER]);

		if (rp_filter == 0)
			fprintf(fp, "rp_filter off ");
		else if (rp_filter == 1)
			fprintf(fp, "rp_filter strict ");
		else if (rp_filter == 2)
			fprintf(fp, "rp_filter loose ");
		else
			fprintf(fp, "rp_filter unknown mode ");
	}
	if (tb[NETCONFA_MC_FORWARDING])
		print_onoff(fp, "mc_forwarding",
				rta_getattr_u32(tb[NETCONFA_MC_FORWARDING]));

	if (tb[NETCONFA_PROXY_NEIGH])
		print_onoff(fp, "proxy_neigh",
				rta_getattr_u32(tb[NETCONFA_PROXY_NEIGH]));

	if (tb[NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN])
		print_onoff(fp, "ignore_routes_with_linkdown",
		     rta_getattr_u32(tb[NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN]));

	if (tb[NETCONFA_INPUT])
		print_onoff(fp, "input", rta_getattr_u32(tb[NETCONFA_INPUT]));

	fprintf(fp, "\n");
	fflush(fp);
	return 0;
}
Ejemplo n.º 30
0
Ref<RouteInfoList> RouteInfo::queryTable()
{
    Ref<RouteInfoList> list = RouteInfoList::create();

    int fd = ::socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
    if (fd == -1) FLUX_SYSTEM_DEBUG_ERROR(errno);

    struct sockaddr_nl src;
    memclr(&src, sizeof(src));
    src.nl_family = AF_NETLINK;
    src.nl_pid = ::getpid();
    if (::bind(fd, (struct sockaddr *)&src, (socklen_t)sizeof(src)) == -1)
        FLUX_SYSTEM_DEBUG_ERROR(errno);

    // send request
    {
        size_t msgLen = NLMSG_LENGTH(sizeof(struct rtmsg));
        struct nlmsghdr *msg = (struct nlmsghdr *)flux::malloc(msgLen);
        int seq = 0;

        memclr(msg, msgLen);
        msg->nlmsg_type = RTM_GETROUTE;
        msg->nlmsg_len = msgLen;
        msg->nlmsg_flags = NLM_F_REQUEST|NLM_F_DUMP;
        msg->nlmsg_pid = src.nl_pid;
        msg->nlmsg_seq = seq++;

        struct rtmsg *data = (struct rtmsg *)NLMSG_DATA(msg);
        data->rtm_table = RT_TABLE_DEFAULT;
        data->rtm_protocol = RTPROT_UNSPEC;

        struct sockaddr_nl dst;
        memclr(&dst, sizeof(dst));
        dst.nl_family = AF_NETLINK;

        struct msghdr hdr;
        memclr(&hdr, sizeof(hdr));

        struct iovec iov = { msg, msgLen };
        hdr.msg_iov = &iov;
        hdr.msg_iovlen = 1;
        hdr.msg_name = (void *)&dst;
        hdr.msg_namelen = sizeof(dst);

        if (::sendmsg(fd, &hdr, 0/*flags*/) == -1)
            FLUX_SYSTEM_DEBUG_ERROR(errno);

        flux::free(msg);
    }

    typedef Map<int, Ref<NetworkInterface> > InterfaceByIndex;
    Ref<InterfaceByIndex> interfaceByIndex = InterfaceByIndex::create();

    // process reply
    {
        struct msghdr hdr;
        memclr(&hdr, sizeof(hdr));

        ssize_t bufSize = ::recvmsg(fd, &hdr, MSG_PEEK|MSG_TRUNC);
        if (bufSize < 0) FLUX_SYSTEM_DEBUG_ERROR(errno);

        void *buf = flux::malloc(bufSize);
        if (!buf) FLUX_SYSTEM_DEBUG_ERROR(errno);

        struct iovec iov = { buf, (size_t)bufSize };
        hdr.msg_iov = &iov;
        hdr.msg_iovlen = 1;
        ssize_t bufFill = ::recvmsg(fd, &hdr, 0/*flags*/);

        if (::close(fd) == -1)
            FLUX_SYSTEM_DEBUG_ERROR(errno);

        struct nlmsghdr *msg = (struct nlmsghdr *)buf;

        for (;NLMSG_OK(msg, unsigned(bufFill)); msg = NLMSG_NEXT(msg, bufFill))
        {
            unsigned msgType = msg->nlmsg_type;

            if (msgType == RTM_NEWROUTE) {
                struct rtmsg *data = (struct rtmsg *)NLMSG_DATA(msg);
                struct rtattr *attr = (struct rtattr *)RTM_RTA(data);
                int attrFill = NLMSG_PAYLOAD(msg, sizeof(struct rtmsg));

                Ref<RouteInfo> info = RouteInfo::create();
                list->append(info);
                info->sourceMask_ = data->rtm_src_len;
                info->destinationMask_ = data->rtm_dst_len;

                for (;RTA_OK(attr, attrFill); attr = RTA_NEXT(attr, attrFill))
                {
                    unsigned attrType = attr->rta_type;

                    if (
                        attrType == RTA_DST ||
                        attrType == RTA_SRC ||
                        attrType == RTA_GATEWAY
                    ) {
                        Ref<SocketAddress> address;
                        struct sockaddr_in addr4;
                        struct sockaddr_in6 addr6;
                        if (data->rtm_family == AF_INET) {
                            memclr(&addr4, sizeof(addr4));
                            // addr.sin_len = sizeof(addr);
                            *(uint8_t *)&addr4 = sizeof(addr4); // uggly, but safe HACK, for BSD4.4
                            addr4.sin_family = AF_INET;
                            addr4.sin_addr = *(struct in_addr *)RTA_DATA(attr);
                            address = SocketAddress::create(&addr4);
                        }
                        else if (data->rtm_family == AF_INET6) {
                            memclr(&addr6, sizeof(addr6));
                            #ifdef SIN6_LEN
                            addr.sin6_len = sizeof(addr6);
                            #endif
                            addr6.sin6_family = AF_INET6;
                            addr6.sin6_addr = *(struct in6_addr *)RTA_DATA(attr);
                            // addr6.sin6_scope_id = data->rtm_scope;
                            address = SocketAddress::create(&addr6);
                        }
                        if (attrType == RTA_DST)
                            info->destination_ = address;
                        else if (attrType == RTA_SRC)
                            info->source_ = address;
                        else if (attrType == RTA_GATEWAY)
                            info->gateway_ = address;
                    }
                    else if (
                        attrType == RTA_IIF ||
                        attrType == RTA_OIF
                    ) {
                        int index = *(int *)RTA_DATA(attr);
                        Ref<NetworkInterface> interface;
                        if (!interfaceByIndex->lookup(index, &interface)) {
                            interface = NetworkInterface::getLink(index);
                            interfaceByIndex->insert(index, interface);
                        }
                        if (attrType == RTA_IIF)
                            info->inputInterface_ = interface->name();
                        else
                            info->outputInterface_ = interface->name();
                    }
                    else if (attrType == RTA_PRIORITY) {
                        info->priority_ = *(int *)RTA_DATA(attr);
                    }
                    else if (attrType == RTA_METRICS) {
                        info->metric_ =  *(int *)RTA_DATA(attr);
                    }
                }
            }
            else if (msgType == NLMSG_DONE) { // paranoid HACK
                break;
            }
        }

        flux::free(buf);
    }

    return list;
}