int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n,
		   void *arg)
{
	FILE *fp = (FILE*)arg;
	struct ifaddrmsg *ifa = NLMSG_DATA(n);
	int len = n->nlmsg_len;
	int deprecated = 0;
	struct rtattr * rta_tb[IFA_MAX+1];
	char abuf[256];
	SPRINT_BUF(b1);

	if (n->nlmsg_type != RTM_NEWADDR && n->nlmsg_type != RTM_DELADDR)
		return 0;
	len -= NLMSG_LENGTH(sizeof(*ifa));
	if (len < 0) {
		fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
		return -1;
	}

	if (filter.flushb && n->nlmsg_type != RTM_NEWADDR)
		return 0;

	parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(ifa), n->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa)));

	if (!rta_tb[IFA_LOCAL])
		rta_tb[IFA_LOCAL] = rta_tb[IFA_ADDRESS];
	if (!rta_tb[IFA_ADDRESS])
		rta_tb[IFA_ADDRESS] = rta_tb[IFA_LOCAL];

	if (filter.ifindex && filter.ifindex != ifa->ifa_index)
		return 0;
	if ((filter.scope^ifa->ifa_scope)&filter.scopemask)
		return 0;
	if ((filter.flags^ifa->ifa_flags)&filter.flagmask)
		return 0;
	if (filter.label) {
		SPRINT_BUF(b1);
		const char *label;
		if (rta_tb[IFA_LABEL])
			label = RTA_DATA(rta_tb[IFA_LABEL]);
		else
			label = ll_idx_n2a(ifa->ifa_index, b1);
		if (fnmatch(filter.label, label, 0) != 0)
			return 0;
	}
	if (filter.pfx.family) {
		if (rta_tb[IFA_LOCAL]) {
			inet_prefix dst;
			memset(&dst, 0, sizeof(dst));
			dst.family = ifa->ifa_family;
			memcpy(&dst.data, RTA_DATA(rta_tb[IFA_LOCAL]), RTA_PAYLOAD(rta_tb[IFA_LOCAL]));
			if (inet_addr_match(&dst, &filter.pfx, filter.pfx.bitlen))
				return 0;
		}
	}

	if (filter.family && filter.family != ifa->ifa_family)
		return 0;

	if (filter.flushb) {
		struct nlmsghdr *fn;
		if (NLMSG_ALIGN(filter.flushp) + n->nlmsg_len > filter.flushe) {
			if (flush_update())
				return -1;
		}
		fn = (struct nlmsghdr*)(filter.flushb + NLMSG_ALIGN(filter.flushp));
		memcpy(fn, n, n->nlmsg_len);
		fn->nlmsg_type = RTM_DELADDR;
		fn->nlmsg_flags = NLM_F_REQUEST;
		fn->nlmsg_seq = ++rth.seq;
		filter.flushp = (((char*)fn) + n->nlmsg_len) - filter.flushb;
		filter.flushed++;
		if (show_stats < 2)
			return 0;
	}

	if (n->nlmsg_type == RTM_DELADDR)
		fprintf(fp, "Deleted ");

	if (filter.oneline || filter.flushb)
		fprintf(fp, "%u: %s", ifa->ifa_index, ll_index_to_name(ifa->ifa_index));
	if (ifa->ifa_family == AF_INET)
		fprintf(fp, "    inet ");
	else if (ifa->ifa_family == AF_INET6)
		fprintf(fp, "    inet6 ");
	else if (ifa->ifa_family == AF_DECnet)
		fprintf(fp, "    dnet ");
	else if (ifa->ifa_family == AF_IPX)
		fprintf(fp, "     ipx ");
	else
		fprintf(fp, "    family %d ", ifa->ifa_family);

	if (rta_tb[IFA_LOCAL]) {
		fprintf(fp, "%s", rt_addr_n2a(ifa->ifa_family,
					      RTA_PAYLOAD(rta_tb[IFA_LOCAL]),
					      RTA_DATA(rta_tb[IFA_LOCAL]),
					      abuf, sizeof(abuf)));

		if (rta_tb[IFA_ADDRESS] == NULL ||
		    memcmp(RTA_DATA(rta_tb[IFA_ADDRESS]), RTA_DATA(rta_tb[IFA_LOCAL]), 4) == 0) {
			fprintf(fp, "/%d ", ifa->ifa_prefixlen);
		} else {
			fprintf(fp, " peer %s/%d ",
				rt_addr_n2a(ifa->ifa_family,
					    RTA_PAYLOAD(rta_tb[IFA_ADDRESS]),
					    RTA_DATA(rta_tb[IFA_ADDRESS]),
					    abuf, sizeof(abuf)),
				ifa->ifa_prefixlen);
		}
	}

	if (rta_tb[IFA_BROADCAST]) {
		fprintf(fp, "brd %s ",
			rt_addr_n2a(ifa->ifa_family,
				    RTA_PAYLOAD(rta_tb[IFA_BROADCAST]),
				    RTA_DATA(rta_tb[IFA_BROADCAST]),
				    abuf, sizeof(abuf)));
	}
	if (rta_tb[IFA_ANYCAST]) {
		fprintf(fp, "any %s ",
			rt_addr_n2a(ifa->ifa_family,
				    RTA_PAYLOAD(rta_tb[IFA_ANYCAST]),
				    RTA_DATA(rta_tb[IFA_ANYCAST]),
				    abuf, sizeof(abuf)));
	}
	fprintf(fp, "scope %s ", rtnl_rtscope_n2a(ifa->ifa_scope, b1, sizeof(b1)));
	if (ifa->ifa_flags&IFA_F_SECONDARY) {
		ifa->ifa_flags &= ~IFA_F_SECONDARY;
		if (ifa->ifa_family == AF_INET6)
			fprintf(fp, "temporary ");
		else
			fprintf(fp, "secondary ");
	}
	if (ifa->ifa_flags&IFA_F_TENTATIVE) {
		ifa->ifa_flags &= ~IFA_F_TENTATIVE;
		fprintf(fp, "tentative ");
	}
	if (ifa->ifa_flags&IFA_F_DEPRECATED) {
		ifa->ifa_flags &= ~IFA_F_DEPRECATED;
		deprecated = 1;
		fprintf(fp, "deprecated ");
	}
	if (ifa->ifa_flags&IFA_F_HOMEADDRESS) {
		ifa->ifa_flags &= ~IFA_F_HOMEADDRESS;
		fprintf(fp, "home ");
	}
	if (ifa->ifa_flags&IFA_F_NODAD) {
		ifa->ifa_flags &= ~IFA_F_NODAD;
		fprintf(fp, "nodad ");
	}
	if (!(ifa->ifa_flags&IFA_F_PERMANENT)) {
		fprintf(fp, "dynamic ");
	} else
		ifa->ifa_flags &= ~IFA_F_PERMANENT;
	if (ifa->ifa_flags&IFA_F_DADFAILED) {
		ifa->ifa_flags &= ~IFA_F_DADFAILED;
		fprintf(fp, "dadfailed ");
	}
	if (ifa->ifa_flags)
		fprintf(fp, "flags %02x ", ifa->ifa_flags);
	if (rta_tb[IFA_LABEL])
		fprintf(fp, "%s", (char*)RTA_DATA(rta_tb[IFA_LABEL]));
	if (rta_tb[IFA_CACHEINFO]) {
		struct ifa_cacheinfo *ci = RTA_DATA(rta_tb[IFA_CACHEINFO]);
		char buf[128];
		fprintf(fp, "%s", _SL_);
		if (ci->ifa_valid == INFINITY_LIFE_TIME)
			sprintf(buf, "valid_lft forever");
		else
			sprintf(buf, "valid_lft %usec", ci->ifa_valid);
		if (ci->ifa_prefered == INFINITY_LIFE_TIME)
			sprintf(buf+strlen(buf), " preferred_lft forever");
		else {
			if (deprecated)
				sprintf(buf+strlen(buf), " preferred_lft %dsec",
					ci->ifa_prefered);
			else
				sprintf(buf+strlen(buf), " preferred_lft %usec",
					ci->ifa_prefered);
		}
		fprintf(fp, "       %s", buf);
	}
	fprintf(fp, "\n");
	fflush(fp);
	return 0;
}
Ejemplo n.º 2
0
static void rtnl_print_ifinfo(struct nlmsghdr *hdr)
{
	struct ifinfomsg *ifi = NLMSG_DATA(hdr);
	struct rtattr *attr = IFLA_RTA(ifi);
	uint32_t attrs_len = IFLA_PAYLOAD(hdr);
	char flags[256];
	char if_addr[64] = {};
	char *af_link = "unknown";

	if (ifi->ifi_family == AF_UNSPEC)
		af_link = "unspec";
	else if (ifi->ifi_family == AF_BRIDGE)
		af_link = "bridge";

	tprintf(" [ Link Family %d (%s%s%s)", ifi->ifi_family,
			colorize_start(bold), af_link, colorize_end());
	tprintf(", Type %d (%s%s%s)", ifi->ifi_type,
			colorize_start(bold),
			device_type2str(ifi->ifi_type),
			colorize_end());
	tprintf(", Index %d", ifi->ifi_index);
	tprintf(", Flags 0x%x (%s%s%s)", ifi->ifi_flags,
			colorize_start(bold),
			rtnl_link_flags2str(ifi->ifi_flags, flags,
				sizeof(flags)),
			colorize_end());
	tprintf(", Change 0x%x (%s%s%s) ]\n", ifi->ifi_change,
			colorize_start(bold),
			rtnl_link_flags2str(ifi->ifi_change, flags,
				sizeof(flags)),
			colorize_end());

	for (; RTA_OK(attr, attrs_len); attr = RTA_NEXT(attr, attrs_len)) {
		switch (attr->rta_type) {
		case IFLA_ADDRESS:
			attr_fmt(attr, "Address %s",
					device_addr2str(RTA_DATA(attr),
						RTA_LEN(attr), ifi->ifi_type,
						if_addr, sizeof(if_addr)));
			break;
		case IFLA_BROADCAST:
			attr_fmt(attr, "Broadcast %s",
					device_addr2str(RTA_DATA(attr),
						RTA_LEN(attr), ifi->ifi_type,
						if_addr, sizeof(if_addr)));
			break;
		case IFLA_IFNAME:
			attr_fmt(attr, "Name %s%s%s",
					colorize_start(bold), RTA_STR(attr),
					colorize_end());
			break;
		case IFLA_MTU:
			attr_fmt(attr, "MTU %d", RTA_INT(attr));
			break;
		case IFLA_LINK:
			attr_fmt(attr, "Link %d", RTA_INT(attr));
			break;
		case IFLA_QDISC:
			attr_fmt(attr, "QDisc %s", RTA_STR(attr));
			break;
		case IFLA_OPERSTATE:
			{
				uint8_t st = RTA_UINT8(attr);
				char states[256];

				attr_fmt(attr, "Operation state 0x%x (%s%s%s)",
						st,
						colorize_start(bold),
						rtnl_link_operstate2str(st,
							states, sizeof(states)),
						colorize_end());
			}
			break;
		case IFLA_LINKMODE:
			{
				uint8_t mode = RTA_UINT8(attr);
				char str[32];

				attr_fmt(attr, "Mode 0x%x (%s%s%s)", mode,
						colorize_start(bold),
						rtnl_link_mode2str(mode, str,
							sizeof(str)),
						colorize_end());
			}
			break;
		case IFLA_GROUP:
			attr_fmt(attr, "Group %d", RTA_INT(attr));
			break;
		case IFLA_TXQLEN:
			attr_fmt(attr, "Tx queue len %d", RTA_INT(attr));
			break;
		case IFLA_NET_NS_PID:
			attr_fmt(attr, "Network namespace pid %d",
					RTA_INT(attr));
			break;
		case IFLA_NET_NS_FD:
			attr_fmt(attr, "Network namespace fd %d",
					RTA_INT(attr));
			break;
		}
	}
}
Ejemplo n.º 3
0
static void rtnl_print_route(struct nlmsghdr *hdr)
{
	struct rtmsg *rtm = NLMSG_DATA(hdr);
	uint32_t attrs_len = RTM_PAYLOAD(hdr);
	struct rtattr *attr = RTM_RTA(rtm);
	struct rta_cacheinfo *ci;
	int hz = get_user_hz();
	char addr_str[256];
	char flags[256];

	tprintf(" [ Route Family %d (%s%s%s)", rtm->rtm_family,
			colorize_start(bold),
			addr_family2str(rtm->rtm_family),
			colorize_end());
	tprintf(", Dst Len %d", rtm->rtm_dst_len);
	tprintf(", Src Len %d", rtm->rtm_src_len);
	tprintf(", ToS %d", rtm->rtm_tos);
	tprintf(", Table %d (%s%s%s)", rtm->rtm_table,
			colorize_start(bold),
			route_table2str(rtm->rtm_table),
			colorize_end());
	tprintf(", Proto %d (%s%s%s)", rtm->rtm_protocol,
			colorize_start(bold),
			route_proto2str(rtm->rtm_protocol),
			colorize_end());
	tprintf(", Scope %d (%s%s%s)", rtm->rtm_scope,
			colorize_start(bold),
			scope2str(rtm->rtm_scope),
			colorize_end());
	tprintf(", Type %d (%s%s%s)", rtm->rtm_type,
			colorize_start(bold),
			route_type2str(rtm->rtm_type),
			colorize_end());
	tprintf(", Flags 0x%x (%s%s%s) ]\n", rtm->rtm_flags,
			colorize_start(bold),
			flags2str(route_flags, rtm->rtm_flags, flags,
				sizeof(flags)),
			colorize_end());

	for (; RTA_OK(attr, attrs_len); attr = RTA_NEXT(attr, attrs_len)) {
		switch (attr->rta_type) {
		case RTA_DST:
			attr_fmt(attr, "Dst %s", addr2str(rtm->rtm_family,
				RTA_DATA(attr), addr_str, sizeof(addr_str)));
			break;
		case RTA_SRC:
			attr_fmt(attr, "Src %s", addr2str(rtm->rtm_family,
				RTA_DATA(attr), addr_str, sizeof(addr_str)));
			break;
		case RTA_IIF:
			attr_fmt(attr, "Iif %d", RTA_INT(attr));
			break;
		case RTA_OIF:
			attr_fmt(attr, "Oif %d", RTA_INT(attr));
			break;
		case RTA_GATEWAY:
			attr_fmt(attr, "Gateway %s", addr2str(rtm->rtm_family,
				RTA_DATA(attr), addr_str, sizeof(addr_str)));
			break;
		case RTA_PRIORITY:
			attr_fmt(attr, "Priority %u", RTA_UINT32(attr));
			break;
		case RTA_PREFSRC:
			attr_fmt(attr, "Pref Src %s", addr2str(rtm->rtm_family,
				RTA_DATA(attr), addr_str, sizeof(addr_str)));
			break;
		case RTA_MARK:
			attr_fmt(attr, "Mark 0x%x", RTA_UINT(attr));
			break;
		case RTA_FLOW:
			attr_fmt(attr, "Flow 0x%x", RTA_UINT(attr));
			break;
		case RTA_TABLE:
			attr_fmt(attr, "Table %d (%s%s%s)", RTA_UINT32(attr),
				colorize_start(bold),
				route_table2str(RTA_UINT32(attr)),
				colorize_end());
			break;
		case RTA_CACHEINFO:
			ci = RTA_DATA(attr);
			tprintf("\tA: Cache (");
			tprintf("expires(%ds)", ci->rta_expires / hz);
			tprintf(", error(%d)", ci->rta_error);
			tprintf(", users(%d)", ci->rta_clntref);
			tprintf(", used(%d)", ci->rta_used);
			tprintf(", last use(%ds)", ci->rta_lastuse / hz);
			tprintf(", id(%d)", ci->rta_id);
			tprintf(", ts(%d)", ci->rta_ts);
			tprintf(", ts age(%ds))", ci->rta_tsage);
			tprintf(", Len %lu\n", RTA_LEN(attr));
			break;
		}
	}
}
Ejemplo n.º 4
0
int xfrm_state_print(const struct sockaddr_nl *who, struct nlmsghdr *n,
		     void *arg)
{
	FILE *fp = (FILE*)arg;
	struct rtattr * tb[XFRMA_MAX+1];
	struct rtattr * rta;
	struct xfrm_usersa_info *xsinfo = NULL;
	struct xfrm_user_expire *xexp = NULL;
	struct xfrm_usersa_id	*xsid = NULL;
	int len = n->nlmsg_len;

	if (n->nlmsg_type != XFRM_MSG_NEWSA &&
	    n->nlmsg_type != XFRM_MSG_DELSA &&
	    n->nlmsg_type != XFRM_MSG_UPDSA &&
	    n->nlmsg_type != XFRM_MSG_EXPIRE) {
		fprintf(stderr, "Not a state: %08x %08x %08x\n",
			n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
		return 0;
	}

	if (n->nlmsg_type == XFRM_MSG_DELSA) {
		/* Dont blame me for this .. Herbert made me do it */
		xsid = NLMSG_DATA(n);
		len -= NLMSG_SPACE(sizeof(*xsid));
	} else if (n->nlmsg_type == XFRM_MSG_EXPIRE) {
		xexp = NLMSG_DATA(n);
		xsinfo = &xexp->state;
		len -= NLMSG_SPACE(sizeof(*xexp));
	} else {
		xexp = NULL;
		xsinfo = NLMSG_DATA(n);
		len -= NLMSG_SPACE(sizeof(*xsinfo));
	}

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

	if (xsinfo && !xfrm_state_filter_match(xsinfo))
		return 0;

	if (n->nlmsg_type == XFRM_MSG_DELSA)
		fprintf(fp, "Deleted ");
	else if (n->nlmsg_type == XFRM_MSG_UPDSA)
		fprintf(fp, "Updated ");
	else if (n->nlmsg_type == XFRM_MSG_EXPIRE)
		fprintf(fp, "Expired ");

	if (n->nlmsg_type == XFRM_MSG_DELSA)
		rta = XFRMSID_RTA(xsid);
	else if (n->nlmsg_type == XFRM_MSG_EXPIRE)
		rta = XFRMEXP_RTA(xexp);
	else
		rta = XFRMS_RTA(xsinfo);

	parse_rtattr(tb, XFRMA_MAX, rta, len);

	if (n->nlmsg_type == XFRM_MSG_DELSA) {
		//xfrm_policy_id_print();

		if (!tb[XFRMA_SA]) {
			fprintf(stderr, "Buggy XFRM_MSG_DELSA: no XFRMA_SA\n");
			return -1;
		}
		if (RTA_PAYLOAD(tb[XFRMA_SA]) < sizeof(*xsinfo)) {
			fprintf(stderr, "Buggy XFRM_MSG_DELPOLICY: too short XFRMA_POLICY len\n");
			return -1;
		}
		xsinfo = RTA_DATA(tb[XFRMA_SA]);
	}

	xfrm_state_info_print(xsinfo, tb, fp, NULL, NULL);

	if (n->nlmsg_type == XFRM_MSG_EXPIRE) {
		fprintf(fp, "\t");
		fprintf(fp, "hard %u", xexp->hard);
		fprintf(fp, "%s", _SL_);
	}

	if (oneline)
		fprintf(fp, "\n");
	fflush(fp);

	return 0;
}
Ejemplo n.º 5
0
/**
 * Scan netlink message in the buffer for IPv6 default route changes.
 */
static int
rtmon_check_defaults(const void *buf, size_t len)
{
    struct nlmsghdr *nh;
    int dfltdiff = 0;

    for (nh = (struct nlmsghdr *)buf;
         NLMSG_OK(nh, len);
         nh = NLMSG_NEXT(nh, len))
    {
        struct rtmsg *rtm;
        struct rtattr *rta;
        int attrlen;
        int delta = 0;
        const void *gwbuf;
        size_t gwlen;
        int oif;

        DPRINTF2(("nlmsg type %d flags 0x%x\n",
                  nh->nlmsg_seq, nh->nlmsg_type, nh->nlmsg_flags));

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

        if (nh->nlmsg_type == NLMSG_ERROR) {
            struct nlmsgerr *ne = (struct nlmsgerr *)NLMSG_DATA(nh);
            DPRINTF2(("> error %d\n", ne->error));
            LWIP_UNUSED_ARG(ne);
            break;
        }

        if (nh->nlmsg_type < RTM_BASE || RTM_MAX <= nh->nlmsg_type) {
            /* shouldn't happen */
            DPRINTF2(("> not an RTM message!\n"));
            continue;
        }


        rtm = (struct rtmsg *)NLMSG_DATA(nh);
        attrlen = RTM_PAYLOAD(nh);

        if (nh->nlmsg_type == RTM_NEWROUTE) {
            delta = +1;
        }
        else if (nh->nlmsg_type == RTM_DELROUTE) {
            delta = -1;
        }
        else {
            /* shouldn't happen */
            continue;
        }

        /*
         * Is this an IPv6 default route in the main table?  (Local
         * table always has ::/0 reject route, hence the last check).
         */
        if (rtm->rtm_family == AF_INET6 /* should always be true */
            && rtm->rtm_dst_len == 0
            && rtm->rtm_table == RT_TABLE_MAIN)
        {
            dfltdiff += delta;
        }
        else {
            /* some other route change */
            continue;
        }


        gwbuf = NULL;
        gwlen = 0;
        oif = -1;

        for (rta = RTM_RTA(rtm);
             RTA_OK(rta, attrlen);
             rta = RTA_NEXT(rta, attrlen))
        {
            if (rta->rta_type == RTA_GATEWAY) {
                gwbuf = RTA_DATA(rta);
                gwlen = RTA_PAYLOAD(rta);
            }
            else if (rta->rta_type == RTA_OIF) {
                /* assert RTA_PAYLOAD(rta) == 4 */
                memcpy(&oif, RTA_DATA(rta), sizeof(oif));
            }
        }

        /* XXX: TODO: note that { oif, gw } was added/removed */
        LWIP_UNUSED_ARG(gwbuf);
        LWIP_UNUSED_ARG(gwlen);
        LWIP_UNUSED_ARG(oif);
    }

    return dfltdiff;
}
Ejemplo n.º 6
0
int xfrm_policy_print(const struct sockaddr_nl *who, struct nlmsghdr *n,
		      void *arg)
{
	struct rtattr * tb[XFRMA_MAX+1];
	struct rtattr * rta;
	struct xfrm_userpolicy_info *xpinfo = NULL;
	struct xfrm_user_polexpire *xpexp = NULL;
	struct xfrm_userpolicy_id *xpid = NULL;
	__u8 ptype = XFRM_POLICY_TYPE_MAIN;
	FILE *fp = (FILE*)arg;
	int len = n->nlmsg_len;

	if (n->nlmsg_type != XFRM_MSG_NEWPOLICY &&
	    n->nlmsg_type != XFRM_MSG_DELPOLICY &&
	    n->nlmsg_type != XFRM_MSG_UPDPOLICY &&
	    n->nlmsg_type != XFRM_MSG_POLEXPIRE) {
		fprintf(stderr, "Not a policy: %08x %08x %08x\n",
			n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
		return 0;
	}

	if (n->nlmsg_type == XFRM_MSG_DELPOLICY)  {
		xpid = NLMSG_DATA(n);
		len -= NLMSG_SPACE(sizeof(*xpid));
	} else if (n->nlmsg_type == XFRM_MSG_POLEXPIRE) {
		xpexp = NLMSG_DATA(n);
		xpinfo = &xpexp->pol;
		len -= NLMSG_SPACE(sizeof(*xpexp));
	} else {
		xpexp = NULL;
		xpinfo = NLMSG_DATA(n);
		len -= NLMSG_SPACE(sizeof(*xpinfo));
	}

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

	if (n->nlmsg_type == XFRM_MSG_DELPOLICY)
		rta = XFRMPID_RTA(xpid);
	else if (n->nlmsg_type == XFRM_MSG_POLEXPIRE)
		rta = XFRMPEXP_RTA(xpexp);
	else
		rta = XFRMP_RTA(xpinfo);

	parse_rtattr(tb, XFRMA_MAX, rta, len);

	if (tb[XFRMA_POLICY_TYPE]) {
		struct xfrm_userpolicy_type *upt;

		if (RTA_PAYLOAD(tb[XFRMA_POLICY_TYPE]) < sizeof(*upt)) {
			fprintf(stderr, "too short XFRMA_POLICY_TYPE len\n");
			return -1;
		}
		upt = (struct xfrm_userpolicy_type *)RTA_DATA(tb[XFRMA_POLICY_TYPE]);
		ptype = upt->type;
	}

	if (xpinfo && !xfrm_policy_filter_match(xpinfo, ptype))
		return 0;

	if (n->nlmsg_type == XFRM_MSG_DELPOLICY)
		fprintf(fp, "Deleted ");
	else if (n->nlmsg_type == XFRM_MSG_UPDPOLICY)
		fprintf(fp, "Updated ");
	else if (n->nlmsg_type == XFRM_MSG_POLEXPIRE)
		fprintf(fp, "Expired ");

	if (n->nlmsg_type == XFRM_MSG_DELPOLICY) {
		//xfrm_policy_id_print();
		if (!tb[XFRMA_POLICY]) {
			fprintf(stderr, "Buggy XFRM_MSG_DELPOLICY: no XFRMA_POLICY\n");
			return -1;
		}
		if (RTA_PAYLOAD(tb[XFRMA_POLICY]) < sizeof(*xpinfo)) {
			fprintf(stderr, "Buggy XFRM_MSG_DELPOLICY: too short XFRMA_POLICY len\n");
			return -1;
		}
		xpinfo = (struct xfrm_userpolicy_info *)RTA_DATA(tb[XFRMA_POLICY]);
	}

	xfrm_policy_info_print(xpinfo, tb, fp, NULL, NULL);

	if (n->nlmsg_type == XFRM_MSG_POLEXPIRE) {
		fprintf(fp, "\t");
		fprintf(fp, "hard %u", xpexp->hard);
		fprintf(fp, "%s", _SL_);
	}

	if (oneline)
		fprintf(fp, "\n");
	fflush(fp);

	return 0;
}
Ejemplo n.º 7
0
static int print_spdinfo( struct nlmsghdr *n, void *arg)
{
	FILE *fp = (FILE*)arg;
	__u32 *f = NLMSG_DATA(n);
	struct rtattr * tb[XFRMA_SPD_MAX+1];
	struct rtattr * rta;

	int len = n->nlmsg_len;

	len -= NLMSG_LENGTH(sizeof(__u32));
	if (len < 0) {
		fprintf(stderr, "SPDinfo: Wrong len %d\n", len);
		return -1;
	}

	rta = XFRMSAPD_RTA(f);
	parse_rtattr(tb, XFRMA_SPD_MAX, rta, len);

	fprintf(fp,"\t SPD");
	if (tb[XFRMA_SPD_INFO]) {
		struct xfrmu_spdinfo *si;

		if (RTA_PAYLOAD(tb[XFRMA_SPD_INFO]) < sizeof(*si)) {
			fprintf(stderr, "SPDinfo: Wrong len %d\n", len);
			return -1;
		}
		si = RTA_DATA(tb[XFRMA_SPD_INFO]);
		fprintf(fp," IN  %d", si->incnt);
		fprintf(fp," OUT %d", si->outcnt);
		fprintf(fp," FWD %d", si->fwdcnt);

		if (show_stats) {
			fprintf(fp," (Sock:");
			fprintf(fp," IN %d", si->inscnt);
			fprintf(fp," OUT %d", si->outscnt);
			fprintf(fp," FWD %d", si->fwdscnt);
			fprintf(fp,")");
		}

		fprintf(fp, "%s", _SL_);
	}
	if (show_stats > 1) {
		struct xfrmu_spdhinfo *sh;

		if (tb[XFRMA_SPD_HINFO]) {
			if (RTA_PAYLOAD(tb[XFRMA_SPD_HINFO]) < sizeof(*sh)) {
				fprintf(stderr, "SPDinfo: Wrong len %d\n", len);
				return -1;
			}
			sh = RTA_DATA(tb[XFRMA_SPD_HINFO]);
			fprintf(fp,"\t SPD buckets:");
			fprintf(fp," count %d", sh->spdhcnt);
			fprintf(fp," Max %d", sh->spdhmcnt);
			fprintf(fp, "%s", _SL_);
		}
		if (tb[XFRMA_SPD_IPV4_HTHRESH]) {
			struct xfrmu_spdhthresh *th;
			if (RTA_PAYLOAD(tb[XFRMA_SPD_IPV4_HTHRESH]) < sizeof(*th)) {
				fprintf(stderr, "SPDinfo: Wrong len %d\n", len);
				return -1;
			}
			th = RTA_DATA(tb[XFRMA_SPD_IPV4_HTHRESH]);
			fprintf(fp,"\t SPD IPv4 thresholds:");
			fprintf(fp," local %d", th->lbits);
			fprintf(fp," remote %d", th->rbits);
			fprintf(fp, "%s", _SL_);

		}
		if (tb[XFRMA_SPD_IPV6_HTHRESH]) {
			struct xfrmu_spdhthresh *th;
			if (RTA_PAYLOAD(tb[XFRMA_SPD_IPV6_HTHRESH]) < sizeof(*th)) {
				fprintf(stderr, "SPDinfo: Wrong len %d\n", len);
				return -1;
			}
			th = RTA_DATA(tb[XFRMA_SPD_IPV6_HTHRESH]);
			fprintf(fp,"\t SPD IPv6 thresholds:");
			fprintf(fp," local %d", th->lbits);
			fprintf(fp," remote %d", th->rbits);
			fprintf(fp, "%s", _SL_);
		}
	}

	if (oneline)
		fprintf(fp, "\n");

        return 0;
}
struct ip4_routing_table * parse_nlmsg(struct nlmsghdr* msg)
{
	char dst_temp[IP4_ALEN];
	char gw_temp[IP4_ALEN];
	unsigned int priority;
	unsigned int interface;
	struct ip4_routing_table *table_pointer = NULL;

	switch (msg->nlmsg_type)
	{
	case NLMSG_ERROR:
	{
		struct nlmsgerr* errorMsg = (struct nlmsgerr*) NLMSG_DATA(msg);
		PRINT_DEBUG("\nrecvd NLMSG_ERROR error seq:%d code:%d...", msg->nlmsg_seq, errorMsg->error);
		break;
	}
	case RTM_NEWROUTE:
	{
		struct rtmsg* rtm = (struct rtmsg*) NLMSG_DATA(msg);
		struct rtattr* rta = RTM_RTA(rtm);
		int rtaLen = msg->nlmsg_len - NLMSG_LENGTH(sizeof(struct rtmsg));
		if (rtm->rtm_type == RTN_UNICAST) // don't consider local, broadcast and unreachable routes
		{
			table_pointer = (struct ip4_routing_table*) malloc(
					sizeof(struct ip4_routing_table));
			memset(table_pointer, 0, sizeof(struct ip4_routing_table)); // zero the routing table entry data
			for (; RTA_OK(rta, rtaLen); rta = RTA_NEXT(rta, rtaLen))
			{
				switch (rta->rta_type)
				{
				case RTA_DST: //destination
					table_pointer->mask = rtm->rtm_dst_len;
					memcpy(dst_temp, RTA_DATA(rta), IP4_ALEN);
					PRINT_DEBUG("received RTA_DST");
					PRINT_DEBUG("dst_str = %u.%u.%u.%u", dst_temp[0]&0xFF, dst_temp[1]&0xFF, dst_temp[2]&0xFF, dst_temp[3]&0xFF);
					table_pointer->dst
							= IP4_ADR_P2N(dst_temp[0]&0xFF, dst_temp[1]&0xFF, dst_temp[2]&0xFF, dst_temp[3]&0xFF);
					break;
				case RTA_GATEWAY: //next hop
					table_pointer->mask = rtm->rtm_dst_len;
					memcpy(gw_temp, RTA_DATA(rta), IP4_ALEN);
					PRINT_DEBUG("received RTA_GATEWAY");
					PRINT_DEBUG("gw_str = %u.%u.%u.%u",gw_temp[0]&0xFF, gw_temp[1]&0xFF, gw_temp[2]&0xFF, gw_temp[3]&0xFF);
					table_pointer->gw
							= IP4_ADR_P2N(gw_temp[0]&0xFF, gw_temp[1]&0xFF, gw_temp[2]&0xFF, gw_temp[3]&0xFF);
					break;
				case RTA_OIF: //interface
					memcpy(&table_pointer->interface, RTA_DATA(rta),
							sizeof(interface));
					PRINT_DEBUG("interface:%u",table_pointer->interface);
					break;
				case RTA_PRIORITY: //metric
					memcpy(&table_pointer->metric, RTA_DATA(rta),
							sizeof(priority));
					PRINT_DEBUG("metric:%u",table_pointer->metric);
					break;
				} //switch(rta->)
			}// for()
		} // if RTN_UNICAST
		return (table_pointer);
	}
	} //switch (msg->nlmsg_type)
	return (NULL);
}
Ejemplo n.º 9
0
static void bionic_ifaddrs_recvaddrs(int fd, struct ifaddrs **ifa, __u32 seq)
{
	char buf[8192];
	struct sockaddr_nl nladdr;
	struct iovec iov = { buf, sizeof(buf) };
	struct ifaddrmsg *m;
	struct rtattr *rta_tb[IFA_MAX + 1];
	struct ifaddrs *I;

	while (1) {
		int status;
		struct nlmsghdr *h;
		struct msghdr msg = {
			(void*) &nladdr, sizeof(nladdr),
			&iov,	1,
			NULL,	0,
			0
		};

		status = recvmsg(fd, &msg, 0);

		if (status <= 0 || nladdr.nl_pid)
			continue;

		h = (struct nlmsghdr*) buf;

		while (NLMSG_OK(h, status)) {
			if (h->nlmsg_seq != seq)
				goto skip_it;

			switch (h->nlmsg_type) {
			case NLMSG_DONE:
				return;
			case NLMSG_ERROR:
				return;
			case RTM_NEWADDR:
				break;
			default:
				goto skip_it;
			}

			m = NLMSG_DATA(h);

#if HAVE_IPV6
			if (m->ifa_family != AF_INET &&
			    m->ifa_family != AF_INET6)
#else /* HAVE_IPV6 */
			if (m->ifa_family != AF_INET)
#endif /* !HAVE_IPV6 */
				goto skip_it;

			if (m->ifa_flags & IFA_F_TENTATIVE)
				goto skip_it;

			memset(rta_tb, 0, sizeof(rta_tb));
			bionic_ifaddrs_parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(m), h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifaddrmsg)));

			if (rta_tb[IFA_LOCAL] == NULL)
				rta_tb[IFA_LOCAL] = rta_tb[IFA_ADDRESS];

			if (rta_tb[IFA_LOCAL] == NULL)
				goto skip_it;

			if (!(I = calloc(1, sizeof(struct ifaddrs))))
				return;

			I->ifa_name = calloc(IFNAMSIZ, sizeof(char));
			I->ifa_flags = m->ifa_index;
			I->ifa_addr = calloc(1, sizeof(struct sockaddr_storage));
			I->ifa_addr->sa_family = m->ifa_family;
			I->ifa_dstaddr = calloc(1, sizeof(struct sockaddr_storage));
			I->ifa_netmask = calloc(1, sizeof(struct sockaddr_storage));

			switch (m->ifa_family) {
			case AF_INET: {
				struct sockaddr_in *sin = (struct sockaddr_in*) I->ifa_addr;
				memcpy(&sin->sin_addr, RTA_DATA(rta_tb[IFA_LOCAL]), sizeof(struct in_addr));
				break;
			}
			case AF_INET6: {
				struct sockaddr_in6 *sin = (struct sockaddr_in6*) I->ifa_addr;
				memcpy(&sin->sin6_addr, RTA_DATA(rta_tb[IFA_LOCAL]), sizeof(struct in6_addr));
				if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr))
					sin->sin6_scope_id = I->ifa_flags;
				break;
			}
			default:
				break;
			}

			I->ifa_next = *ifa;
			*ifa = I;

skip_it:
			h = NLMSG_NEXT(h, status);
		}

		if (msg.msg_flags & MSG_TRUNC)
			continue;
	}
}
Ejemplo n.º 10
0
/* Netlink interface link lookup filter */
static int
netlink_if_link_filter(struct sockaddr_nl *snl, struct nlmsghdr *h)
{
	struct ifinfomsg *ifi;
	struct rtattr *tb[IFLA_MAX + 1];
	interface_t *ifp;
	int i, len;
	char *name;

	ifi = NLMSG_DATA(h);

	if (h->nlmsg_type != RTM_NEWLINK)
		return 0;

	len = h->nlmsg_len - NLMSG_LENGTH(sizeof (struct ifinfomsg));
	if (len < 0)
		return -1;

	/* Interface name lookup */
	memset(tb, 0, sizeof (tb));
	parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
	if (tb[IFLA_IFNAME] == NULL)
		return -1;
	name = (char *) RTA_DATA(tb[IFLA_IFNAME]);

	/* Return if loopback */
	if (ifi->ifi_type == ARPHRD_LOOPBACK)
		return 0;

	/* Skip it if already exist */
	ifp = if_get_by_ifname(name);
	if (ifp) {
		if (!ifp->vmac) {
			vmac_reflect_flags(ifi);
			ifp->flags = ifi->ifi_flags;
		}
		return 0;
	}

	/* Fill the interface structure */
	ifp = (interface_t *) MALLOC(sizeof(interface_t));
	memcpy(ifp->ifname, name, strlen(name));
	ifp->ifindex = ifi->ifi_index;
	ifp->mtu = *(int *) RTA_DATA(tb[IFLA_MTU]);
	ifp->hw_type = ifi->ifi_type;

	if (!ifp->vmac) {
		vmac_reflect_flags(ifi);
		ifp->flags = ifi->ifi_flags;
		ifp->base_ifindex = ifi->ifi_index;
	}

	if (tb[IFLA_ADDRESS]) {
		int hw_addr_len = RTA_PAYLOAD(tb[IFLA_ADDRESS]);

		if (hw_addr_len > IF_HWADDR_MAX)
			log_message(LOG_ERR, "MAC address for %s is too large: %d",
			       name, hw_addr_len);
		else {
			ifp->hw_addr_len = hw_addr_len;
			memcpy(ifp->hw_addr, RTA_DATA(tb[IFLA_ADDRESS]),
			       hw_addr_len);
			for (i = 0; i < hw_addr_len; i++)
				if (ifp->hw_addr[i] != 0)
					break;
			if (i == hw_addr_len)
				ifp->hw_addr_len = 0;
			else
				ifp->hw_addr_len = hw_addr_len;
		}
	}

	/* Queue this new interface_t */
	if_add_queue(ifp);
	return 0;
}
Ejemplo n.º 11
0
/**
 * virNetDevVPortProfileGetStatus:
 *
 * tb: top level netlink response attributes + values
 * vf: The virtual function used in the request
 * instanceId: instanceId of the interface (vm uuid in case of 802.1Qbh)
 * is8021Qbg: whether this function is call for 8021Qbg
 * status: pointer to a uint16 where the status will be written into
 *
 * Get the status from the IFLA_PORT_RESPONSE field; Returns 0 in
 * case of success, < 0 otherwise with error having been reported
 */
static int
virNetDevVPortProfileGetStatus(struct nlattr **tb, int32_t vf,
                               const unsigned char *instanceId,
                               bool nltarget_kernel,
                               bool is8021Qbg,
                               uint16_t *status)
{
    int rc = -1;
    struct nlattr *tb_port[IFLA_PORT_MAX + 1] = { NULL, };

    if (vf == PORT_SELF_VF && nltarget_kernel) {
        if (tb[IFLA_PORT_SELF]) {
            if (nla_parse_nested(tb_port, IFLA_PORT_MAX, tb[IFLA_PORT_SELF],
                                 ifla_port_policy)) {
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("error parsing IFLA_PORT_SELF part"));
                goto cleanup;
            }
        } else {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("IFLA_PORT_SELF is missing"));
            goto cleanup;
        }
    } else {
        if (tb[IFLA_VF_PORTS]) {
            int rem;
            bool found = false;
            struct nlattr *tb_vf_ports = { NULL, };

            nla_for_each_nested(tb_vf_ports, tb[IFLA_VF_PORTS], rem) {

                if (nla_type(tb_vf_ports) != IFLA_VF_PORT) {
                    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                   _("error while iterating over "
                                     "IFLA_VF_PORTS part"));
                    goto cleanup;
                }

                if (nla_parse_nested(tb_port, IFLA_PORT_MAX, tb_vf_ports,
                                     ifla_port_policy)) {
                    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                   _("error parsing IFLA_VF_PORT part"));
                    goto cleanup;
                }

                if (instanceId &&
                    tb_port[IFLA_PORT_INSTANCE_UUID] &&
                    !memcmp(instanceId,
                            (unsigned char *)
                                   RTA_DATA(tb_port[IFLA_PORT_INSTANCE_UUID]),
                            VIR_UUID_BUFLEN) &&
                    tb_port[IFLA_PORT_VF] &&
                    vf == *(uint32_t *)RTA_DATA(tb_port[IFLA_PORT_VF])) {
                        found = true;
                        break;
                }
            }

            if (!found) {
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("Could not find netlink response with "
                                 "expected parameters"));
                goto cleanup;
            }
        } else {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("IFLA_VF_PORTS is missing"));
            goto cleanup;
        }
    }
Ejemplo n.º 12
0
static void recvaddrs(int fd, struct ifaddrs **ifa, __u32 seq)
{
	char	buf[8192];
	struct sockaddr_nl nladdr;
	struct iovec iov = { buf, sizeof(buf) };
	struct ifaddrmsg *m;
	struct rtattr * rta_tb[IFA_MAX+1];
	struct ifaddrs *I;

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

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

		status = recvmsg(fd, &msg, 0);

		if (status < 0)
			continue;

		if (status == 0)
			return;

		if (nladdr.nl_pid) /* Message not from kernel */
			continue;

		h = (struct nlmsghdr*)buf;
		while (NLMSG_OK(h, status)) {
			if (h->nlmsg_seq != seq)
				goto skip_it;

			if (h->nlmsg_type == NLMSG_DONE)
				return;

			if (h->nlmsg_type == NLMSG_ERROR)
				return;

			if (h->nlmsg_type != RTM_NEWADDR)
				goto skip_it;

			m = NLMSG_DATA(h);

			if (m->ifa_family != AF_INET &&
			    m->ifa_family != AF_INET6)
				goto skip_it;

			if (m->ifa_flags&IFA_F_TENTATIVE)
				goto skip_it;

			memset(rta_tb, 0, sizeof(rta_tb));
			parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(m), h->nlmsg_len - NLMSG_LENGTH(sizeof(*m)));

			if (rta_tb[IFA_LOCAL] == NULL)
				rta_tb[IFA_LOCAL] = rta_tb[IFA_ADDRESS];
			if (rta_tb[IFA_LOCAL] == NULL)
				goto skip_it;
			
			I = malloc(sizeof(struct ifaddrs));
			if (!I)
				return;
			memset(I, 0, sizeof(*I));

			I->ifa_ifindex = m->ifa_index;
			I->ifa_addr = (struct sockaddr*)&I->ifa_addrbuf;
			I->ifa_addr->sa_family = m->ifa_family;
			if (m->ifa_family == AF_INET) {
				struct sockaddr_in *sin = (void*)I->ifa_addr;
				memcpy(&sin->sin_addr, RTA_DATA(rta_tb[IFA_LOCAL]), 4);
			} else {
				struct sockaddr_in6 *sin = (void*)I->ifa_addr;
				memcpy(&sin->sin6_addr, RTA_DATA(rta_tb[IFA_LOCAL]), 16);
				if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr))
					sin->sin6_scope_id = I->ifa_ifindex;
			}
			I->ifa_next = *ifa;
			*ifa = I;

skip_it:
			h = NLMSG_NEXT(h, status);
		}
		if (msg.msg_flags & MSG_TRUNC)
			continue;
	}
	return;
}
Ejemplo n.º 13
0
static struct if_nameindex *
if_nameindex_netlink (void)
{
  struct netlink_handle nh = { 0, 0, 0, NULL, NULL };
  struct if_nameindex *idx = NULL;

  if (__netlink_open (&nh) < 0)
    return NULL;


  /* Tell the kernel that we wish to get a list of all
     active interfaces.  Collect all data for every interface.  */
  if (__netlink_request (&nh, RTM_GETLINK) < 0)
    goto exit_free;

  /* Count the interfaces.  */
  unsigned int nifs = 0;
  for (struct netlink_res *nlp = nh.nlm_list; nlp; nlp = nlp->next)
    {
      struct nlmsghdr *nlh;
      size_t size = nlp->size;

      if (nlp->nlh == NULL)
	continue;

      /* Walk through all entries we got from the kernel and look, which
         message type they contain.  */
      for (nlh = nlp->nlh; NLMSG_OK (nlh, size); nlh = NLMSG_NEXT (nlh, size))
	{
	  /* Check if the message is what we want.  */
	  if ((pid_t) nlh->nlmsg_pid != nh.pid || nlh->nlmsg_seq != nlp->seq)
	    continue;

	  if (nlh->nlmsg_type == NLMSG_DONE)
	    break;		/* ok */

	  if (nlh->nlmsg_type == RTM_NEWLINK)
	    ++nifs;
	}
    }

  idx = malloc ((nifs + 1) * sizeof (struct if_nameindex));
  if (idx == NULL)
    {
    nomem:
      __set_errno (ENOBUFS);
      goto exit_free;
    }

  /* Add the interfaces.  */
  nifs = 0;
  for (struct netlink_res *nlp = nh.nlm_list; nlp; nlp = nlp->next)
    {
      struct nlmsghdr *nlh;
      size_t size = nlp->size;

      if (nlp->nlh == NULL)
	continue;

      /* Walk through all entries we got from the kernel and look, which
         message type they contain.  */
      for (nlh = nlp->nlh; NLMSG_OK (nlh, size); nlh = NLMSG_NEXT (nlh, size))
	{
	  /* Check if the message is what we want.  */
	  if ((pid_t) nlh->nlmsg_pid != nh.pid || nlh->nlmsg_seq != nlp->seq)
	    continue;

	  if (nlh->nlmsg_type == NLMSG_DONE)
	    break;		/* ok */

	  if (nlh->nlmsg_type == RTM_NEWLINK)
	    {
	      struct ifinfomsg *ifim = (struct ifinfomsg *) NLMSG_DATA (nlh);
	      struct rtattr *rta = IFLA_RTA (ifim);
	      size_t rtasize = IFLA_PAYLOAD (nlh);

	      idx[nifs].if_index = ifim->ifi_index;

	      while (RTA_OK (rta, rtasize))
		{
		  char *rta_data = RTA_DATA (rta);
		  size_t rta_payload = RTA_PAYLOAD (rta);

		  if (rta->rta_type == IFLA_IFNAME)
		    {
		      idx[nifs].if_name = __strndup (rta_data, rta_payload);
		      if (idx[nifs].if_name == NULL)
			{
			  idx[nifs].if_index = 0;
			  __if_freenameindex (idx);
			  idx = NULL;
			  goto nomem;
			}
		      break;
		    }

		  rta = RTA_NEXT (rta, rtasize);
		}

	      ++nifs;
	    }
	}
    }

  idx[nifs].if_index = 0;
  idx[nifs].if_name = NULL;

 exit_free:
  __netlink_free_handle (&nh);
  __netlink_close (&nh);

  return idx;
}
Ejemplo n.º 14
0
int
fillup_entry_info(netsnmp_arp_entry *entry, struct nlmsghdr *nlmp)
{
    struct ndmsg   *rtmp;
    struct in6_addr *in6p;
    struct rtattr  *tb[NDA_MAX + 1], *rta;
    size_t          in_len, out_len;
    unsigned int    i;
    int             length;
    char            addr[40];
    u_char         *buf;
    u_char         *hwaddr;

    rtmp = (struct ndmsg *) NLMSG_DATA(nlmp);
    if (nlmp->nlmsg_type != RTM_NEWNEIGH) {
        snmp_log(LOG_ERR, "Wrong netlink message type %d\n", nlmp->nlmsg_type);
        return -1;
    }

    if (rtmp->ndm_state != NUD_NOARP) {
        memset(tb, 0, sizeof(struct rtattr *) * (NDA_MAX + 1));
        length = nlmp->nlmsg_len - NLMSG_LENGTH(sizeof(*rtmp));
        if (length < 0) {
            snmp_log(LOG_ERR, "netlink message length %d < %d is invalid\n",
                     nlmp->nlmsg_len, NLMSG_LENGTH(sizeof(*rtmp)));
            return -1;
        }
        /*
         * this is what the kernel-removed NDA_RTA define did 
         */
        rta = ((struct rtattr *) (((char *) (rtmp)) +
                                  NLMSG_ALIGN(sizeof(struct ndmsg))));
        while (RTA_OK(rta, length)) {
            if (rta->rta_type <= NDA_MAX)
                tb[rta->rta_type] = rta;
            rta = RTA_NEXT(rta, length);
        }
        if (length) {
            snmp_log(LOG_ERR, "Received uneven number of netlink"
                        " messages - %d bytes remaining\n", length);
            return -1;
        }
        /*
         * Fill up the index
         */
        entry->if_index = rtmp->ndm_ifindex;
        /*
         * Fill up ip address 
         */
        if (tb[NDA_DST]) {
            memset(&addr, '\0', sizeof(addr));
            in6p = (struct in6_addr *) RTA_DATA(tb[NDA_DST]);
            sprintf(addr, NIP6_FMT, NIP6(*in6p));
            in_len = entry->arp_ipaddress_len =
                sizeof(entry->arp_ipaddress);
            netsnmp_assert(16 == in_len);
            out_len = 0;
            buf = entry->arp_ipaddress;
            if (1 != netsnmp_hex_to_binary(&buf, &in_len,
                                           &out_len, 0, addr, ":")) {
                snmp_log(LOG_ERR, "error parsing '%s', skipping\n",
                         entry->arp_ipaddress);
                return -1;
            }
            netsnmp_assert(16 == out_len);
            entry->arp_ipaddress_len = out_len;
        }
        if (tb[NDA_LLADDR]) {
            memset(&addr, '\0', sizeof(addr));
            hwaddr = RTA_DATA(tb[NDA_LLADDR]);
            entry->arp_physaddress_len = RTA_PAYLOAD(tb[NDA_LLADDR]);
            buf = entry->arp_physaddress;
            for (i = 0; i < entry->arp_physaddress_len; i++)
                entry->arp_physaddress[i] = hwaddr[i];
        }

        switch (rtmp->ndm_state) {
        case NUD_INCOMPLETE:
            entry->arp_state = INETNETTOMEDIASTATE_INCOMPLETE;
            break;
        case NUD_REACHABLE:
        case NUD_PERMANENT:
            entry->arp_state = INETNETTOMEDIASTATE_REACHABLE;
            break;
        case NUD_STALE:
            entry->arp_state = INETNETTOMEDIASTATE_STALE;
            break;
        case NUD_DELAY:
            entry->arp_state = INETNETTOMEDIASTATE_DELAY;
            break;
        case NUD_PROBE:
            entry->arp_state = INETNETTOMEDIASTATE_PROBE;
            break;
        case NUD_FAILED:
            entry->arp_state = INETNETTOMEDIASTATE_INVALID;
            break;
        case NUD_NONE:
            entry->arp_state = INETNETTOMEDIASTATE_UNKNOWN;
            break;
        default:
            snmp_log(LOG_ERR, "Unrecognized ARP entry state %d", rtmp->ndm_state);
            break;
        }

        switch (rtmp->ndm_state) {
        case NUD_INCOMPLETE:
        case NUD_FAILED:
        case NUD_NONE:
            entry->arp_type = INETNETTOMEDIATYPE_INVALID;
            break;
        case NUD_REACHABLE:
        case NUD_STALE:
        case NUD_DELAY:
        case NUD_PROBE:
            entry->arp_type = INETNETTOMEDIATYPE_DYNAMIC;
            break;
        case NUD_PERMANENT:
            entry->arp_type = INETNETTOMEDIATYPE_STATIC;
            break;
        default:
            entry->arp_type = INETNETTOMEDIATYPE_LOCAL;
            break;
        }
    } else {
        return -1;              /* could not create data for this interface */
    }

    return 0;
}
Ejemplo n.º 15
0
static int filter_nlmsg(struct nlmsghdr *n, struct rtattr **tb, int host_len)
{
	struct rtmsg *r = NLMSG_DATA(n);
	inet_prefix dst;
	inet_prefix src;
	inet_prefix via;
	inet_prefix prefsrc;
	__u32 table;
	static int ip6_multiple_tables;

	table = rtm_get_table(r, tb);

	if (r->rtm_family == AF_INET6 && table != RT_TABLE_MAIN)
		ip6_multiple_tables = 1;

	if (filter.cloned == !(r->rtm_flags&RTM_F_CLONED))
		return 0;

	if (r->rtm_family == AF_INET6 && !ip6_multiple_tables) {
		if (filter.tb) {
			if (filter.tb == RT_TABLE_LOCAL) {
				if (r->rtm_type != RTN_LOCAL)
					return 0;
			} else if (filter.tb == RT_TABLE_MAIN) {
				if (r->rtm_type == RTN_LOCAL)
					return 0;
			} else {
				return 0;
			}
		}
	} else {
		if (filter.tb > 0 && filter.tb != table)
			return 0;
	}
	if ((filter.protocol^r->rtm_protocol)&filter.protocolmask)
		return 0;
	if ((filter.scope^r->rtm_scope)&filter.scopemask)
		return 0;
	if ((filter.type^r->rtm_type)&filter.typemask)
		return 0;
	if ((filter.tos^r->rtm_tos)&filter.tosmask)
		return 0;
	if (filter.rdst.family &&
	    (r->rtm_family != filter.rdst.family || filter.rdst.bitlen > r->rtm_dst_len))
		return 0;
	if (filter.mdst.family &&
	    (r->rtm_family != filter.mdst.family ||
	     (filter.mdst.bitlen >= 0 && filter.mdst.bitlen < r->rtm_dst_len)))
		return 0;
	if (filter.rsrc.family &&
	    (r->rtm_family != filter.rsrc.family || filter.rsrc.bitlen > r->rtm_src_len))
		return 0;
	if (filter.msrc.family &&
	    (r->rtm_family != filter.msrc.family ||
	     (filter.msrc.bitlen >= 0 && filter.msrc.bitlen < r->rtm_src_len)))
		return 0;
	if (filter.rvia.family && r->rtm_family != filter.rvia.family)
		return 0;
	if (filter.rprefsrc.family && r->rtm_family != filter.rprefsrc.family)
		return 0;

	memset(&dst, 0, sizeof(dst));
	dst.family = r->rtm_family;
	if (tb[RTA_DST])
		memcpy(&dst.data, RTA_DATA(tb[RTA_DST]), (r->rtm_dst_len+7)/8);
	if (filter.rsrc.family || filter.msrc.family) {
		memset(&src, 0, sizeof(src));
		src.family = r->rtm_family;
		if (tb[RTA_SRC])
			memcpy(&src.data, RTA_DATA(tb[RTA_SRC]), (r->rtm_src_len+7)/8);
	}
	if (filter.rvia.bitlen>0) {
		memset(&via, 0, sizeof(via));
		via.family = r->rtm_family;
		if (tb[RTA_GATEWAY])
			memcpy(&via.data, RTA_DATA(tb[RTA_GATEWAY]), host_len/8);
	}
	if (filter.rprefsrc.bitlen>0) {
		memset(&prefsrc, 0, sizeof(prefsrc));
		prefsrc.family = r->rtm_family;
		if (tb[RTA_PREFSRC])
			memcpy(&prefsrc.data, RTA_DATA(tb[RTA_PREFSRC]), host_len/8);
	}

	if (filter.rdst.family && inet_addr_match(&dst, &filter.rdst, filter.rdst.bitlen))
		return 0;
	if (filter.mdst.family && filter.mdst.bitlen >= 0 &&
	    inet_addr_match(&dst, &filter.mdst, r->rtm_dst_len))
		return 0;

	if (filter.rsrc.family && inet_addr_match(&src, &filter.rsrc, filter.rsrc.bitlen))
		return 0;
	if (filter.msrc.family && filter.msrc.bitlen >= 0 &&
	    inet_addr_match(&src, &filter.msrc, r->rtm_src_len))
		return 0;

	if (filter.rvia.family && inet_addr_match(&via, &filter.rvia, filter.rvia.bitlen))
		return 0;
	if (filter.rprefsrc.family && inet_addr_match(&prefsrc, &filter.rprefsrc, filter.rprefsrc.bitlen))
		return 0;
	if (filter.realmmask) {
		__u32 realms = 0;
		if (tb[RTA_FLOW])
			realms = rta_getattr_u32(tb[RTA_FLOW]);
		if ((realms^filter.realm)&filter.realmmask)
			return 0;
	}
	if (filter.iifmask) {
		int iif = 0;
		if (tb[RTA_IIF])
			iif = *(int*)RTA_DATA(tb[RTA_IIF]);
		if ((iif^filter.iif)&filter.iifmask)
			return 0;
	}
	if (filter.oifmask) {
		int oif = 0;
		if (tb[RTA_OIF])
			oif = *(int*)RTA_DATA(tb[RTA_OIF]);
		if ((oif^filter.oif)&filter.oifmask)
			return 0;
	}
	if (filter.markmask) {
		int mark = 0;
		if (tb[RTA_MARK])
			mark = *(int *)RTA_DATA(tb[RTA_MARK]);
		if ((mark ^ filter.mark) & filter.markmask)
			return 0;
	}
	if (filter.flushb &&
	    r->rtm_family == AF_INET6 &&
	    r->rtm_dst_len == 0 &&
	    r->rtm_type == RTN_UNREACHABLE &&
	    tb[RTA_PRIORITY] &&
	    *(int*)RTA_DATA(tb[RTA_PRIORITY]) == -1)
		return 0;

	return 1;
}
Ejemplo n.º 16
0
int get_hw_addr(struct in_addr *gw_ip, char *iface, unsigned char *hw_mac)
{
	char buf[8192];
	struct ndmsg req;
	struct nlmsghdr *nlhdr;

	if (!gw_ip || !hw_mac) {
		return -1;
	}
	// Send RTM_GETNEIGH request
	req.ndm_family = AF_INET;
	req.ndm_ifindex = if_nametoindex(iface);
	req.ndm_state = NUD_REACHABLE;
	req.ndm_type = NDA_LLADDR;

	int sock = send_nl_req(RTM_GETNEIGH, 1, &req, sizeof(req));

	// Read responses
	unsigned nl_len = read_nl_sock(sock, buf, sizeof(buf));
	if (nl_len <= 0) {
		return -1;
	}
	// Parse responses
	nlhdr = (struct nlmsghdr *)buf;
	while (NLMSG_OK(nlhdr, nl_len)) {
		struct rtattr *rt_attr;
		struct rtmsg *rt_msg;
		int rt_len;
		unsigned char mac[6];
		struct in_addr dst_ip;
		int correct_ip = 0;

		rt_msg = (struct rtmsg *) NLMSG_DATA(nlhdr);
		
		if ((rt_msg->rtm_family != AF_INET)) {
			return -1;
		}
	
		rt_attr = (struct rtattr *) RTM_RTA(rt_msg);
		rt_len = RTM_PAYLOAD(nlhdr);
		while (RTA_OK(rt_attr, rt_len)) {
			switch (rt_attr->rta_type) {
			case NDA_LLADDR: 
				assert(RTA_PAYLOAD(rt_attr) == IFHWADDRLEN);
				memcpy(mac, RTA_DATA(rt_attr), IFHWADDRLEN);
				break;
			case NDA_DST:
				assert(RTA_PAYLOAD(rt_attr) == sizeof(dst_ip));
				memcpy(&dst_ip, RTA_DATA(rt_attr), sizeof(dst_ip));
				if (memcmp(&dst_ip, gw_ip, sizeof(dst_ip)) == 0) {
					correct_ip = 1;
				}
				break;
			}
			rt_attr = RTA_NEXT(rt_attr, rt_len);
		}
		if (correct_ip) {
			memcpy(hw_mac, mac, IFHWADDRLEN);
			return 0;
		}
		nlhdr = NLMSG_NEXT(nlhdr, nl_len);	
	}
	return -1;				
}
Ejemplo n.º 17
0
int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
{
	FILE *fp = (FILE*)arg;
	struct rtmsg *r = NLMSG_DATA(n);
	int len = n->nlmsg_len;
	struct rtattr * tb[RTA_MAX+1];
	char abuf[256];
	int host_len = -1;
	__u32 table;
	SPRINT_BUF(b1);
	static int hz;

	if (n->nlmsg_type != RTM_NEWROUTE && n->nlmsg_type != RTM_DELROUTE) {
		fprintf(stderr, "Not a route: %08x %08x %08x\n",
			n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
		return 0;
	}
	if (filter.flushb && n->nlmsg_type != RTM_NEWROUTE)
		return 0;
	len -= NLMSG_LENGTH(sizeof(*r));
	if (len < 0) {
		fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
		return -1;
	}

	host_len = calc_host_len(r);

	parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len);
	table = rtm_get_table(r, tb);

	if (!filter_nlmsg(n, tb, host_len))
		return 0;

	if (filter.flushb) {
		struct nlmsghdr *fn;
		if (NLMSG_ALIGN(filter.flushp) + n->nlmsg_len > filter.flushe) {
			if (flush_update())
				return -1;
		}
		fn = (struct nlmsghdr*)(filter.flushb + NLMSG_ALIGN(filter.flushp));
		memcpy(fn, n, n->nlmsg_len);
		fn->nlmsg_type = RTM_DELROUTE;
		fn->nlmsg_flags = NLM_F_REQUEST;
		fn->nlmsg_seq = ++rth.seq;
		filter.flushp = (((char*)fn) + n->nlmsg_len) - filter.flushb;
		filter.flushed++;
		if (show_stats < 2)
			return 0;
	}

	if (n->nlmsg_type == RTM_DELROUTE)
		fprintf(fp, "Deleted ");
	if (r->rtm_type != RTN_UNICAST && !filter.type)
		fprintf(fp, "%s ", rtnl_rtntype_n2a(r->rtm_type, b1, sizeof(b1)));

	if (tb[RTA_DST]) {
		if (r->rtm_dst_len != host_len) {
			fprintf(fp, "%s/%u ", rt_addr_n2a(r->rtm_family,
							 RTA_PAYLOAD(tb[RTA_DST]),
							 RTA_DATA(tb[RTA_DST]),
							 abuf, sizeof(abuf)),
				r->rtm_dst_len
				);
		} else {
			fprintf(fp, "%s ", format_host(r->rtm_family,
						       RTA_PAYLOAD(tb[RTA_DST]),
						       RTA_DATA(tb[RTA_DST]),
						       abuf, sizeof(abuf))
				);
		}
	} else if (r->rtm_dst_len) {
		fprintf(fp, "0/%d ", r->rtm_dst_len);
	} else {
		fprintf(fp, "default ");
	}
	if (tb[RTA_SRC]) {
		if (r->rtm_src_len != host_len) {
			fprintf(fp, "from %s/%u ", rt_addr_n2a(r->rtm_family,
							 RTA_PAYLOAD(tb[RTA_SRC]),
							 RTA_DATA(tb[RTA_SRC]),
							 abuf, sizeof(abuf)),
				r->rtm_src_len
				);
		} else {
			fprintf(fp, "from %s ", format_host(r->rtm_family,
						       RTA_PAYLOAD(tb[RTA_SRC]),
						       RTA_DATA(tb[RTA_SRC]),
						       abuf, sizeof(abuf))
				);
		}
	} else if (r->rtm_src_len) {
		fprintf(fp, "from 0/%u ", r->rtm_src_len);
	}
	if (r->rtm_tos && filter.tosmask != -1) {
		SPRINT_BUF(b1);
		fprintf(fp, "tos %s ", rtnl_dsfield_n2a(r->rtm_tos, b1, sizeof(b1)));
	}

	if (tb[RTA_GATEWAY] && filter.rvia.bitlen != host_len) {
		fprintf(fp, "via %s ",
			format_host(r->rtm_family,
				    RTA_PAYLOAD(tb[RTA_GATEWAY]),
				    RTA_DATA(tb[RTA_GATEWAY]),
				    abuf, sizeof(abuf)));
	}
	if (tb[RTA_OIF] && filter.oifmask != -1)
		fprintf(fp, "dev %s ", ll_index_to_name(*(int*)RTA_DATA(tb[RTA_OIF])));

	if (!(r->rtm_flags&RTM_F_CLONED)) {
		if (table != RT_TABLE_MAIN && !filter.tb)
			fprintf(fp, " table %s ", rtnl_rttable_n2a(table, b1, sizeof(b1)));
		if (r->rtm_protocol != RTPROT_BOOT && filter.protocolmask != -1)
			fprintf(fp, " proto %s ", rtnl_rtprot_n2a(r->rtm_protocol, b1, sizeof(b1)));
		if (r->rtm_scope != RT_SCOPE_UNIVERSE && filter.scopemask != -1)
			fprintf(fp, " scope %s ", rtnl_rtscope_n2a(r->rtm_scope, b1, sizeof(b1)));
	}
	if (tb[RTA_PREFSRC] && filter.rprefsrc.bitlen != host_len) {
		/* Do not use format_host(). It is our local addr
		   and symbolic name will not be useful.
		 */
		fprintf(fp, " src %s ",
			rt_addr_n2a(r->rtm_family,
				    RTA_PAYLOAD(tb[RTA_PREFSRC]),
				    RTA_DATA(tb[RTA_PREFSRC]),
				    abuf, sizeof(abuf)));
	}
	if (tb[RTA_PRIORITY])
		fprintf(fp, " metric %u ", rta_getattr_u32(tb[RTA_PRIORITY]));
	if (r->rtm_flags & RTNH_F_DEAD)
		fprintf(fp, "dead ");
	if (r->rtm_flags & RTNH_F_ONLINK)
		fprintf(fp, "onlink ");
	if (r->rtm_flags & RTNH_F_PERVASIVE)
		fprintf(fp, "pervasive ");
	if (r->rtm_flags & RTM_F_NOTIFY)
		fprintf(fp, "notify ");
	if (tb[RTA_MARK]) {
		unsigned int mark = *(unsigned int*)RTA_DATA(tb[RTA_MARK]);
		if (mark) {
			if (mark >= 16)
				fprintf(fp, " mark 0x%x", mark);
			else
				fprintf(fp, " mark %u", mark);
		}
	}

	if (tb[RTA_FLOW] && filter.realmmask != ~0U) {
		__u32 to = rta_getattr_u32(tb[RTA_FLOW]);
		__u32 from = to>>16;
		to &= 0xFFFF;
		fprintf(fp, "realm%s ", from ? "s" : "");
		if (from) {
			fprintf(fp, "%s/",
				rtnl_rtrealm_n2a(from, b1, sizeof(b1)));
		}
		fprintf(fp, "%s ",
			rtnl_rtrealm_n2a(to, b1, sizeof(b1)));
	}
Ejemplo n.º 18
0
json_t* make_interface_file() {
	json_t *interfaces_json = json_object();
	json_t *ifTable_json = json_object();
	json_t *ifEntry_array = json_array();

	struct rtnl_handle rth = { .fd = -1 };

	if (rtnl_open(&rth, 0) < 0) {
		exit(1);
	}

	if (rtnl_wilddump_request(&rth, AF_PACKET, RTM_GETLINK) < 0) {
		perror("Cannot send dump request");
		exit(1);
	}

	struct nlmsg_list *linfo = NULL;

	if (rtnl_dump_filter(&rth, store_nlmsg, &linfo, NULL, NULL) < 0) {
		fprintf(stderr, "Dump terminated\n");
		exit(1);
	}

	struct nlmsg_list *l, *n;

	for (l = linfo; l; l = n) {
		n = l->next;
		struct nlmsghdr *nlhdr = &(l->h);
		struct ifinfomsg *ifimsg = NLMSG_DATA(nlhdr);

		// Process Data of Netlink Message as ifinfomsg
		if (ifimsg->ifi_family != AF_UNSPEC && ifimsg->ifi_family != AF_INET6) {
			printf("error family: %d\n", ifimsg->ifi_family);
			continue;
		}

		// Add Each Parameter to json file
		json_t *interface_json = json_object();
		json_t *linux_json = json_object();

		json_object_set_new(interface_json, "ifIndex", json_integer(ifimsg->ifi_index));
		json_object_set_new(linux_json, "ifi_type", json_integer(ifimsg->ifi_type));
		json_object_set_new(linux_json, "ifi_flags", json_integer(ifimsg->ifi_flags));

		// Analyze rtattr Message
		int len = nlhdr->nlmsg_len - NLMSG_LENGTH(sizeof(*ifimsg));;

		struct rtattr *tb[IFLA_MAX+1];
		parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifimsg), len);

		if (tb[IFLA_IFNAME]) {
			// printf("\n%s\n", (char *)RTA_DATA(tb[IFLA_IFNAME]));
			json_object_set_new(interface_json, "ifDscr", json_string((char *)RTA_DATA(tb[IFLA_IFNAME])));
		}

		if (tb[IFLA_MTU]) {
			// printf("%d\n", *(int *)RTA_DATA(tb[IFLA_MTU]));
			json_object_set_new(interface_json, "ifMtu", json_integer(*(int *)RTA_DATA(tb[IFLA_MTU])));
		}

		static const char *oper_states[] = {
			"UNKNOWN", "NOTPRESENT", "DOWN", "LOWERLAYERDOWN",
			"TESTING", "DORMANT",	 "UP"
		};

		if (tb[IFLA_OPERSTATE]) {
			__u8 state = *(__u8 *)RTA_DATA(tb[IFLA_OPERSTATE]);
			if (state >= sizeof(oper_states)/sizeof(oper_states[0])){
				fprintf(stderr, "state %#x ", state);
			}
			else{
				// printf("state %s ", oper_states[state]);
				json_object_set_new(interface_json, "ifOperStatus", json_string(oper_states[state]));
			}
		}

		if (tb[IFLA_ADDRESS]) {
			char abuf[64];
			json_object_set_new(interface_json, "ifPhysAddress", json_string(ll_addr_n2a(RTA_DATA(tb[IFLA_ADDRESS]), RTA_PAYLOAD(tb[IFLA_ADDRESS]), ifimsg->ifi_type, abuf, sizeof(abuf))));
		}

		if (tb[IFLA_LINKINFO]) {
			struct rtattr *linkinfo[IFLA_INFO_MAX+1];
			char *kind;

			parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]);

			if (!linkinfo[IFLA_INFO_KIND]){
				json_object_set_new(interface_json, "IFLA_LINKINFO", json_integer((int)RTA_DATA(tb[IFLA_LINKINFO])));
				// printf("%d\n", (int)RTA_DATA(tb[IFLA_LINKINFO]));
				// continue;
			} else {
				kind = RTA_DATA(linkinfo[IFLA_INFO_KIND]);
				if (strcmp(kind, "bridge") == 0 && tb[IFLA_IFNAME]) {
					json_object_set_new(interface_json, "ifType", json_string(kind));
					char *bridge_name = (char *)RTA_DATA(tb[IFLA_IFNAME]);
					json_t *bridge_list_json = get_bridge_name(bridge_name);
					json_object_set_new(linux_json, "bridge", bridge_list_json);
				}
				else {
					continue;
				}
			}
		}

		json_object_set_new(interface_json, "linux", linux_json);
		json_array_append(ifEntry_array, interface_json);
	}

	json_object_set_new(ifTable_json, "ifEntry", ifEntry_array);
	json_object_set_new(interfaces_json, "ifTable", ifTable_json);

	free(l);

	rtnl_close(&rth);

	return interfaces_json;
}
Ejemplo n.º 19
0
/*
 * With an existing policy of nlmsg, make new nlmsg for deleting the policy
 * and store it to buffer.
 */
static int xfrm_policy_keep(const struct sockaddr_nl *who,
			    struct nlmsghdr *n,
			    void *arg)
{
	struct xfrm_buffer *xb = (struct xfrm_buffer *)arg;
	struct rtnl_handle *rth = xb->rth;
	struct xfrm_userpolicy_info *xpinfo = NLMSG_DATA(n);
	int len = n->nlmsg_len;
	struct rtattr *tb[XFRMA_MAX+1];
	__u8 ptype = XFRM_POLICY_TYPE_MAIN;
	struct nlmsghdr *new_n;
	struct xfrm_userpolicy_id *xpid;

	if (n->nlmsg_type != XFRM_MSG_NEWPOLICY) {
		fprintf(stderr, "Not a policy: %08x %08x %08x\n",
			n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
		return 0;
	}

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

	parse_rtattr(tb, XFRMA_MAX, XFRMP_RTA(xpinfo), len);

	if (tb[XFRMA_POLICY_TYPE]) {
		struct xfrm_userpolicy_type *upt;

		if (RTA_PAYLOAD(tb[XFRMA_POLICY_TYPE]) < sizeof(*upt)) {
			fprintf(stderr, "too short XFRMA_POLICY_TYPE len\n");
			return -1;
		}
		upt = (struct xfrm_userpolicy_type *)RTA_DATA(tb[XFRMA_POLICY_TYPE]);
		ptype = upt->type;
	}

	if (!xfrm_policy_filter_match(xpinfo, ptype))
		return 0;

	if (xb->offset > xb->size) {
		fprintf(stderr, "Policy buffer overflow\n");
		return -1;
	}

	new_n = (struct nlmsghdr *)(xb->buf + xb->offset);
	new_n->nlmsg_len = NLMSG_LENGTH(sizeof(*xpid));
	new_n->nlmsg_flags = NLM_F_REQUEST;
	new_n->nlmsg_type = XFRM_MSG_DELPOLICY;
	new_n->nlmsg_seq = ++rth->seq;

	xpid = NLMSG_DATA(new_n);
	memcpy(&xpid->sel, &xpinfo->sel, sizeof(xpid->sel));
	xpid->dir = xpinfo->dir;
	xpid->index = xpinfo->index;

	xb->offset += new_n->nlmsg_len;
	xb->nlmsg_count ++;

	return 0;
}
Ejemplo n.º 20
0
static int rtnetlink_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
                                 int type, u32 pid, u32 seq, u32 change,
                                 unsigned int flags)
{
    struct ifinfomsg *r;
    struct nlmsghdr  *nlh;
    unsigned char	 *b = skb->tail;

    nlh = NLMSG_NEW(skb, pid, seq, type, sizeof(*r), flags);
    r = NLMSG_DATA(nlh);
    r->ifi_family = AF_UNSPEC;
    r->__ifi_pad = 0;
    r->ifi_type = dev->type;
    r->ifi_index = dev->ifindex;
    r->ifi_flags = dev_get_flags(dev);
    r->ifi_change = change;

    RTA_PUT(skb, IFLA_IFNAME, strlen(dev->name)+1, dev->name);

    if (1) {
        u32 txqlen = dev->tx_queue_len;
        RTA_PUT(skb, IFLA_TXQLEN, sizeof(txqlen), &txqlen);
    }

    if (1) {
        u32 weight = dev->weight;
        RTA_PUT(skb, IFLA_WEIGHT, sizeof(weight), &weight);
    }

    if (1) {
        u8 operstate = netif_running(dev)?dev->operstate:IF_OPER_DOWN;
        u8 link_mode = dev->link_mode;
        RTA_PUT(skb, IFLA_OPERSTATE, sizeof(operstate), &operstate);
        RTA_PUT(skb, IFLA_LINKMODE, sizeof(link_mode), &link_mode);
    }

    if (1) {
        struct rtnl_link_ifmap map = {
            .mem_start   = dev->mem_start,
            .mem_end     = dev->mem_end,
            .base_addr   = dev->base_addr,
            .irq         = dev->irq,
            .dma         = dev->dma,
            .port        = dev->if_port,
        };
        RTA_PUT(skb, IFLA_MAP, sizeof(map), &map);
    }

    if (dev->addr_len) {
        RTA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr);
        RTA_PUT(skb, IFLA_BROADCAST, dev->addr_len, dev->broadcast);
    }

    if (1) {
        u32 mtu = dev->mtu;
        RTA_PUT(skb, IFLA_MTU, sizeof(mtu), &mtu);
    }

    if (dev->ifindex != dev->iflink) {
        u32 iflink = dev->iflink;
        RTA_PUT(skb, IFLA_LINK, sizeof(iflink), &iflink);
    }

    if (dev->qdisc_sleeping)
        RTA_PUT(skb, IFLA_QDISC,
                strlen(dev->qdisc_sleeping->ops->id) + 1,
                dev->qdisc_sleeping->ops->id);

    if (dev->master) {
        u32 master = dev->master->ifindex;
        RTA_PUT(skb, IFLA_MASTER, sizeof(master), &master);
    }

    if (dev->get_stats) {
        unsigned long *stats = (unsigned long*)dev->get_stats(dev);
        if (stats) {
            struct rtattr  *a;
            __u32	       *s;
            int		i;
            int		n = sizeof(struct rtnl_link_stats)/4;

            a = __RTA_PUT(skb, IFLA_STATS, n*4);
            s = RTA_DATA(a);
            for (i=0; i<n; i++)
                s[i] = stats[i];
        }
    }
    nlh->nlmsg_len = skb->tail - b;
    return skb->len;

nlmsg_failure:
rtattr_failure:
    skb_trim(skb, b - skb->data);
    return -1;
}

static int rtnetlink_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
{
    int idx;
    int s_idx = cb->args[0];
    struct net_device *dev;

    read_lock(&dev_base_lock);
    for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) {
        if (idx < s_idx)
            continue;
        if (rtnetlink_fill_ifinfo(skb, dev, RTM_NEWLINK,
                                  NETLINK_CB(cb->skb).pid,
                                  cb->nlh->nlmsg_seq, 0,
                                  NLM_F_MULTI) <= 0)
            break;
    }
    read_unlock(&dev_base_lock);
    cb->args[0] = idx;

    return skb->len;
}
Ejemplo n.º 21
0
/* n = the response to a CTRL_CMD_GETFAMILY message */
static int
genl_get_mcast_group_id(struct nlmsghdr *n)
{
	/*
	 *  Attribute table.  Note the type name "rtattr" which means "route
	 *  attribute".  This is a vestige of one of netlink's main uses:
	 *  routing.
	 */
	struct rtattr *tb[CTRL_ATTR_MAX + 1];
	/* place for the generic netlink header in the incoming message */
	struct genlmsghdr ghdr;
	/* length of the attribute and payload */
	int len = n->nlmsg_len - NLMSG_LENGTH(GENL_HDRLEN);
	/* Pointer to the attribute portion of the message */
	struct rtattr *attrs;

	if (len < 0) {
		printf("Netlink: CTRL_CMD_GETFAMILY response, "
			"wrong controller message len: %d\n", len);
		return -1;
	}

	if (n->nlmsg_type != GENL_ID_CTRL) {
		printf("Netlink: Not a controller message, nlmsg_len=%d "
			"nlmsg_type=0x%x\n", n->nlmsg_len, n->nlmsg_type);
		return 0;
	}

	/* copy generic netlink header into structure */
	memcpy(&ghdr, NLMSG_DATA(n), GENL_HDRLEN);

	if (ghdr.cmd != CTRL_CMD_GETFAMILY &&
	    ghdr.cmd != CTRL_CMD_DELFAMILY &&
	    ghdr.cmd != CTRL_CMD_NEWFAMILY &&
	    ghdr.cmd != CTRL_CMD_NEWMCAST_GRP &&
	    ghdr.cmd != CTRL_CMD_DELMCAST_GRP) {
		printf("Netlink: Unknown controller command %d\n", ghdr.cmd);
		return 0;
	}

	/* set attrs to point to the attribute */
	attrs = (struct rtattr *)(NLMSG_DATA(n) + GENL_HDRLEN);
	/* Read the table from the message into "tb".  This actually just  */
	/* places pointers into the message into tb[].  */
	parse_rtattr(tb, CTRL_ATTR_MAX, attrs, len);

	/* if a family ID attribute is present, get it */
	if (tb[CTRL_ATTR_FAMILY_ID])
	{
		acpi_event_family_id =
			*((__u32 *)RTA_DATA(tb[CTRL_ATTR_FAMILY_ID]));
	}

	/* if a "multicast groups" attribute is present... */
	if (tb[CTRL_ATTR_MCAST_GROUPS]) {
		struct rtattr *tb2[GENL_MAX_FAM_GRPS + 1];
		int i;

		/* get the group table within this attribute  */
		parse_rtattr_nested(tb2, GENL_MAX_FAM_GRPS,
			tb[CTRL_ATTR_MCAST_GROUPS]);

		/* for each group */
		for (i = 0; i < GENL_MAX_FAM_GRPS; i++)
			/* if this group is valid */
			if (tb2[i])
				/* Parse the ID.  If successful, we're done. */
				if (!get_ctrl_grp_id(tb2[i]))
					return 0;
	}

	return -1;
}
Ejemplo n.º 22
0
static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
{
    struct ifinfomsg  *ifm = NLMSG_DATA(nlh);
    struct rtattr    **ida = arg;
    struct net_device *dev;
    int err, send_addr_notify = 0;

    if (ifm->ifi_index >= 0)
        dev = dev_get_by_index(ifm->ifi_index);
    else if (ida[IFLA_IFNAME - 1]) {
        char ifname[IFNAMSIZ];

        if (rtattr_strlcpy(ifname, ida[IFLA_IFNAME - 1],
                           IFNAMSIZ) >= IFNAMSIZ)
            return -EINVAL;
        dev = dev_get_by_name(ifname);
    } else
        return -EINVAL;

    if (!dev)
        return -ENODEV;

    err = -EINVAL;

    if (ifm->ifi_flags)
        dev_change_flags(dev, ifm->ifi_flags);

    if (ida[IFLA_MAP - 1]) {
        struct rtnl_link_ifmap *u_map;
        struct ifmap k_map;

        if (!dev->set_config) {
            err = -EOPNOTSUPP;
            goto out;
        }

        if (!netif_device_present(dev)) {
            err = -ENODEV;
            goto out;
        }

        if (ida[IFLA_MAP - 1]->rta_len != RTA_LENGTH(sizeof(*u_map)))
            goto out;

        u_map = RTA_DATA(ida[IFLA_MAP - 1]);

        k_map.mem_start = (unsigned long) u_map->mem_start;
        k_map.mem_end = (unsigned long) u_map->mem_end;
        k_map.base_addr = (unsigned short) u_map->base_addr;
        k_map.irq = (unsigned char) u_map->irq;
        k_map.dma = (unsigned char) u_map->dma;
        k_map.port = (unsigned char) u_map->port;

        err = dev->set_config(dev, &k_map);

        if (err)
            goto out;
    }

    if (ida[IFLA_ADDRESS - 1]) {
        struct sockaddr *sa;
        int len;

        if (!dev->set_mac_address) {
            err = -EOPNOTSUPP;
            goto out;
        }
        if (!netif_device_present(dev)) {
            err = -ENODEV;
            goto out;
        }
        if (ida[IFLA_ADDRESS - 1]->rta_len != RTA_LENGTH(dev->addr_len))
            goto out;

        len = sizeof(sa_family_t) + dev->addr_len;
        sa = kmalloc(len, GFP_KERNEL);
        if (!sa) {
            err = -ENOMEM;
            goto out;
        }
        sa->sa_family = dev->type;
        memcpy(sa->sa_data, RTA_DATA(ida[IFLA_ADDRESS - 1]),
               dev->addr_len);
        err = dev->set_mac_address(dev, sa);
        kfree(sa);
        if (err)
            goto out;
        send_addr_notify = 1;
    }

    if (ida[IFLA_BROADCAST - 1]) {
        if (ida[IFLA_BROADCAST - 1]->rta_len != RTA_LENGTH(dev->addr_len))
            goto out;
        memcpy(dev->broadcast, RTA_DATA(ida[IFLA_BROADCAST - 1]),
               dev->addr_len);
        send_addr_notify = 1;
    }

    if (ida[IFLA_MTU - 1]) {
        if (ida[IFLA_MTU - 1]->rta_len != RTA_LENGTH(sizeof(u32)))
            goto out;
        err = dev_set_mtu(dev, *((u32 *) RTA_DATA(ida[IFLA_MTU - 1])));

        if (err)
            goto out;

    }

    if (ida[IFLA_TXQLEN - 1]) {
        if (ida[IFLA_TXQLEN - 1]->rta_len != RTA_LENGTH(sizeof(u32)))
            goto out;

        dev->tx_queue_len = *((u32 *) RTA_DATA(ida[IFLA_TXQLEN - 1]));
    }

    if (ida[IFLA_WEIGHT - 1]) {
        if (ida[IFLA_WEIGHT - 1]->rta_len != RTA_LENGTH(sizeof(u32)))
            goto out;

        dev->weight = *((u32 *) RTA_DATA(ida[IFLA_WEIGHT - 1]));
    }

    if (ida[IFLA_OPERSTATE - 1]) {
        if (ida[IFLA_OPERSTATE - 1]->rta_len != RTA_LENGTH(sizeof(u8)))
            goto out;

        set_operstate(dev, *((u8 *) RTA_DATA(ida[IFLA_OPERSTATE - 1])));
    }

    if (ida[IFLA_LINKMODE - 1]) {
        if (ida[IFLA_LINKMODE - 1]->rta_len != RTA_LENGTH(sizeof(u8)))
            goto out;

        write_lock_bh(&dev_base_lock);
        dev->link_mode = *((u8 *) RTA_DATA(ida[IFLA_LINKMODE - 1]));
        write_unlock_bh(&dev_base_lock);
    }

    if (ifm->ifi_index >= 0 && ida[IFLA_IFNAME - 1]) {
        char ifname[IFNAMSIZ];

        if (rtattr_strlcpy(ifname, ida[IFLA_IFNAME - 1],
                           IFNAMSIZ) >= IFNAMSIZ)
            goto out;
        err = dev_change_name(dev, ifname);
        if (err)
            goto out;
    }

#ifdef CONFIG_NET_WIRELESS_RTNETLINK
    if (ida[IFLA_WIRELESS - 1]) {

        /* Call Wireless Extensions.
         * Various stuff checked in there... */
        err = wireless_rtnetlink_set(dev, RTA_DATA(ida[IFLA_WIRELESS - 1]), ida[IFLA_WIRELESS - 1]->rta_len);
        if (err)
            goto out;
    }
#endif	/* CONFIG_NET_WIRELESS_RTNETLINK */

    err = 0;

out:
    if (send_addr_notify)
        call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);

    dev_put(dev);
    return err;
}
Ejemplo n.º 23
0
static int addr2mac_init_linux()
{
  struct nlmsghdr   *nlmsg;
  struct ndmsg      *ndmsg;
  struct rtattr     *rta, *tb[NDA_MAX];
  struct sockaddr_nl snl;
  struct msghdr      msg;
  struct iovec       iov;
  struct timeval     tv;
  pid_t              pid;
  uint8_t            buf[16384];
  ssize_t            ssize;
  ssize_t            len;
  int                rlen;
  int                fd = -1;
  void              *ip, *mac;
  int                iptype;

  pid = getpid();

  memset(buf, 0, sizeof(buf));
  nlmsg = (struct nlmsghdr *)buf;
  nlmsg->nlmsg_len   = NLMSG_LENGTH(sizeof(struct ndmsg));
  nlmsg->nlmsg_type  = RTM_GETNEIGH;
  nlmsg->nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT | NLM_F_MATCH;
  nlmsg->nlmsg_seq   = 0;
  nlmsg->nlmsg_pid   = pid;

  ndmsg = NLMSG_DATA(nlmsg);
  ndmsg->ndm_family = AF_UNSPEC;

  if((fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) == -1)
    {
      printerror(errno, strerror, __func__, "could not open netlink");
      goto err;
    }

  len = nlmsg->nlmsg_len;
  if((ssize = send(fd, buf, len, 0)) < len)
    {
      if(ssize == -1)
	{
	  printerror(errno, strerror, __func__, "could not send netlink");
	}
      goto err;
    }

  for(;;)
    {
      iov.iov_base = buf;
      iov.iov_len = sizeof(buf);

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

      if((len = recvmsg(fd, &msg, 0)) == -1)
	{
	  if(errno == EINTR) continue;
	  printerror(errno, strerror, __func__, "could not recvmsg");
	  goto err;
	}

      gettimeofday_wrap(&tv);

      nlmsg = (struct nlmsghdr *)buf;
      while(NLMSG_OK(nlmsg, len))
	{
	  if(nlmsg->nlmsg_pid != pid || nlmsg->nlmsg_seq != 0)
	    {
	      goto skip;
	    }

	  if(nlmsg->nlmsg_type == NLMSG_DONE)
	    {
	      goto done;
	    }

	  if(nlmsg->nlmsg_type == NLMSG_ERROR)
	    {
	      scamper_debug(__func__, "nlmsg error");
	      goto err;
	    }

	  /* get current neighbour entries only */
	  if(nlmsg->nlmsg_type != RTM_NEWNEIGH)
	    {
	      goto skip;
	    }

	  /* make sure the address is reachable */
	  ndmsg = NLMSG_DATA(nlmsg);
	  if((ndmsg->ndm_state & NUD_REACHABLE) == 0)
	    {
	      goto skip;
	    }

	  /* make sure we can process this address type */
	  switch(ndmsg->ndm_family)
	    {
	    case AF_INET:
	      iptype = SCAMPER_ADDR_TYPE_IPV4;
	      break;

	    case AF_INET6:
	      iptype = SCAMPER_ADDR_TYPE_IPV6;
	      break;

	    default:
	      goto skip;
	    }

	  /* fill a table with parameters from the payload */
	  memset(tb, 0, sizeof(tb));
	  rlen = nlmsg->nlmsg_len - NLMSG_LENGTH(sizeof(struct ndmsg));
	  for(rta = NDA_RTA(ndmsg); RTA_OK(rta,rlen); rta = RTA_NEXT(rta,rlen))
	    {
	      if(rta->rta_type >= NDA_MAX)
		continue;
	      tb[rta->rta_type] = rta;
	    }

	  /*
	   * skip if we don't have a destination IP address, or if
	   * we don't have an ethernet mac address
	   */
	  if(tb[NDA_DST] == NULL ||
	     tb[NDA_LLADDR] == NULL || RTA_PAYLOAD(tb[NDA_LLADDR]) != 6)
	    {
	      goto skip;
	    }

	  ip = RTA_DATA(tb[NDA_DST]);
	  mac = RTA_DATA(tb[NDA_LLADDR]);

	  addr2mac_add(ndmsg->ndm_ifindex, iptype, ip, mac, tv.tv_sec+600);

	skip:
	  nlmsg = NLMSG_NEXT(nlmsg, len);
	}
    }

 done:
  close(fd);
  return 0;

 err:
  close(fd);
  return -1;
}
Ejemplo n.º 24
0
static int do_getlink(struct sk_buff *in_skb, struct nlmsghdr* in_nlh, void *arg)
{
    struct ifinfomsg  *ifm = NLMSG_DATA(in_nlh);
    struct rtattr    **ida = arg;
    struct net_device *dev;
    struct ifinfomsg *r;
    struct nlmsghdr  *nlh;
    int err = -ENOBUFS;
    struct sk_buff *skb;
    unsigned char	 *b;
    char *iw_buf = NULL;
    int iw_buf_len = 0;

    if (ifm->ifi_index >= 0)
        dev = dev_get_by_index(ifm->ifi_index);
    else
        return -EINVAL;
    if (!dev)
        return -ENODEV;

#ifdef CONFIG_NET_WIRELESS_RTNETLINK
    if (ida[IFLA_WIRELESS - 1]) {

        /* Call Wireless Extensions. We need to know the size before
         * we can alloc. Various stuff checked in there... */
        err = wireless_rtnetlink_get(dev, RTA_DATA(ida[IFLA_WIRELESS - 1]), ida[IFLA_WIRELESS - 1]->rta_len, &iw_buf, &iw_buf_len);
        if (err)
            goto out;
    }
#endif	/* CONFIG_NET_WIRELESS_RTNETLINK */

    /* Create a skb big enough to include all the data.
     * Some requests are way bigger than 4k... Jean II */
    skb = alloc_skb((NLMSG_LENGTH(sizeof(*r))) + (RTA_SPACE(iw_buf_len)),
                    GFP_KERNEL);
    if (!skb)
        goto out;
    b = skb->tail;

    /* Put in the message the usual good stuff */
    nlh = NLMSG_PUT(skb, NETLINK_CB(in_skb).pid, in_nlh->nlmsg_seq,
                    RTM_NEWLINK, sizeof(*r));
    r = NLMSG_DATA(nlh);
    r->ifi_family = AF_UNSPEC;
    r->__ifi_pad = 0;
    r->ifi_type = dev->type;
    r->ifi_index = dev->ifindex;
    r->ifi_flags = dev->flags;
    r->ifi_change = 0;

    /* Put the wireless payload if it exist */
    if(iw_buf != NULL)
        RTA_PUT(skb, IFLA_WIRELESS, iw_buf_len,
                iw_buf + IW_EV_POINT_OFF);

    nlh->nlmsg_len = skb->tail - b;

    /* Needed ? */
    NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;

    err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT);
    if (err > 0)
        err = 0;
out:
    if(iw_buf != NULL)
        kfree(iw_buf);
    dev_put(dev);
    return err;

rtattr_failure:
nlmsg_failure:
    kfree_skb(skb);
    goto out;
}
Ejemplo n.º 25
0
int print_prefix(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
{
	FILE *fp = (FILE*)arg;
	struct prefixmsg *prefix = NLMSG_DATA(n);
	int len = n->nlmsg_len;
	struct rtattr * tb[RTA_MAX+1];
	int family = preferred_family;

	if (n->nlmsg_type != RTM_NEWPREFIX) {
		fprintf(stderr, "Not a prefix: %08x %08x %08x\n",
			n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
		return 0;
	}

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

	if (family == AF_UNSPEC)
		family = AF_INET6;
	if (family != AF_INET6)
		return 0;

	if (prefix->prefix_family != AF_INET6) {
		fprintf(stderr, "wrong family %d\n", prefix->prefix_family);
		return 0;
	}
	if (prefix->prefix_type != ND_OPT_PREFIX_INFORMATION) {
		fprintf(stderr, "wrong ND type %d\n", prefix->prefix_type);
		return 0;
	}

	parse_rtattr(tb, RTA_MAX, RTM_RTA(prefix), len);

	fprintf(fp, "prefix ");

	if (tb[PREFIX_ADDRESS]) {
		struct in6_addr *pfx;
		char abuf[256];

		pfx = (struct in6_addr *)RTA_DATA(tb[PREFIX_ADDRESS]);

		memset(abuf, '\0', sizeof(abuf));
		fprintf(fp, "%s", rt_addr_n2a(family, sizeof(*pfx), pfx,
					      abuf, sizeof(abuf)));
	}
	fprintf(fp, "/%u ", prefix->prefix_len);

	fprintf(fp, "dev %s ", ll_index_to_name(prefix->prefix_ifindex));

	if (prefix->prefix_flags & IF_PREFIX_ONLINK)
		fprintf(fp, "onlink ");
	if (prefix->prefix_flags & IF_PREFIX_AUTOCONF)
		fprintf(fp, "autoconf ");

	if (tb[PREFIX_CACHEINFO]) {
		struct prefix_cacheinfo *pc;
		pc = (struct prefix_cacheinfo *)tb[PREFIX_CACHEINFO];

		fprintf(fp, "valid %u ", pc->valid_time);
		fprintf(fp, "preferred %u ", pc->preferred_time);
	}

	fprintf(fp, "\n");
	fflush(fp);

	return 0;
}
Ejemplo n.º 26
0
static int netlink_getack(int fd)
{
	struct {
		struct nlmsghdr nlh;
		char buf[SIZE_NLMSG];
	} resp;
	struct iovec iov = { &resp, sizeof(resp), };
	struct msghdr msg = { .msg_iov = &iov, .msg_iovlen = 1, };
	ssize_t ret;
	struct nlmsghdr *nlh = &resp.nlh;

	ret = recvmsg(fd, &msg, 0);
	if (ret == -1)
		return -errno;

	if (msg.msg_flags & MSG_TRUNC)
		return -EIO;

	for (; NLMSG_OK(nlh, (size_t)ret); nlh = NLMSG_NEXT(nlh, ret)) {

		if (nlh->nlmsg_type == NLMSG_DONE)
			return 0;

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

	return -EIO;
}

/* Set local address */
static int netlink_setaddr(uint32_t ifa_index, uint8_t ifa_local)
{
	struct ifaddrmsg *ifa;
	struct rtattr *rta;
	uint32_t reqlen = NLMSG_LENGTH(NLMSG_ALIGN(sizeof(*ifa))
				+ RTA_SPACE(1));
	struct req {
		struct nlmsghdr nlh;
		char buf[512];
	} req = {
		.nlh = {
			.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
			.nlmsg_type = RTM_NEWADDR,
			.nlmsg_pid = getpid(),
			.nlmsg_len = reqlen,
		},
	};
	int fd;
	int error;
	struct sockaddr_nl addr = { .nl_family = AF_NETLINK, };

	ifa = NLMSG_DATA(&req.nlh);
	ifa->ifa_family = AF_PHONET;
	ifa->ifa_prefixlen = 0;
	ifa->ifa_index = ifa_index;

	rta = IFA_RTA(ifa);
	rta->rta_type = IFA_LOCAL;
	rta->rta_len = RTA_LENGTH(1);
	*(uint8_t *)RTA_DATA(rta) = ifa_local;

	fd = netlink_socket();
	if (fd == -1)
		return -errno;

	if (sendto(fd, &req, reqlen, 0, (void *)&addr, sizeof(addr)) == -1)
		error = -errno;
	else
		error = netlink_getack(fd);

	close(fd);

	return error;
}

int g_pn_netlink_set_address(GIsiModem *idx, uint8_t local)
{
	uint32_t ifindex = g_isi_modem_index(idx);

	if (ifindex == 0)
		return -ENODEV;

	if (local != PN_DEV_PC && local != PN_DEV_SOS)
		return -EINVAL;

	return netlink_setaddr(ifindex, local);
}
Ejemplo n.º 27
0
static void rtnl_print_ifaddr(struct nlmsghdr *hdr)
{
	struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
	uint32_t attrs_len = IFA_PAYLOAD(hdr);
	struct rtattr *attr = IFA_RTA(ifa);
	struct ifa_cacheinfo *ci;
	char addr_str[256];
	char flags[256];

	tprintf(" [ Address Family %d (%s%s%s)", ifa->ifa_family,
			colorize_start(bold),
			addr_family2str(ifa->ifa_family),
			colorize_end());
	tprintf(", Prefix Len %d", ifa->ifa_prefixlen);
	tprintf(", Flags %d (%s%s%s)", ifa->ifa_flags,
			colorize_start(bold),
			rtnl_addr_flags2str(ifa->ifa_flags, flags,
				sizeof(flags)),
			colorize_end());
	tprintf(", Scope %d (%s%s%s)", ifa->ifa_scope,
			colorize_start(bold),
			scope2str(ifa->ifa_scope),
			colorize_end());
	tprintf(", Link Index %d ]\n", ifa->ifa_index);

	for (; RTA_OK(attr, attrs_len); attr = RTA_NEXT(attr, attrs_len)) {
		switch (attr->rta_type) {
		case IFA_LOCAL:
			attr_fmt(attr, "Local %s", addr2str(ifa->ifa_family,
				RTA_DATA(attr), addr_str, sizeof(addr_str)));
			break;
		case IFA_ADDRESS:
			attr_fmt(attr, "Address %s", addr2str(ifa->ifa_family,
				RTA_DATA(attr), addr_str, sizeof(addr_str)));
			break;
		case IFA_BROADCAST:
			attr_fmt(attr, "Broadcast %s",
					addr2str(ifa->ifa_family,
						RTA_DATA(attr), addr_str,
						sizeof(addr_str)));
			break;
		case IFA_MULTICAST:
			attr_fmt(attr, "Multicast %s",
					addr2str(ifa->ifa_family,
						RTA_DATA(attr), addr_str,
						sizeof(addr_str)));
			break;
		case IFA_ANYCAST:
			attr_fmt(attr, "Anycast %s", addr2str(ifa->ifa_family,
				RTA_DATA(attr), addr_str, sizeof(addr_str)));
			break;
#ifdef IFA_FLAGS
		case IFA_FLAGS:
			attr_fmt(attr, "Flags %d (%s%s%s)", RTA_INT(attr),
				colorize_start(bold),
				rtnl_addr_flags2str(RTA_INT(attr),
					flags, sizeof(flags)),
				colorize_end());
			break;
#endif
		case IFA_LABEL:
			attr_fmt(attr, "Label %s", RTA_STR(attr));
			break;
		case IFA_CACHEINFO:
			ci = RTA_DATA(attr);
			tprintf("\tA: Cache (");

			if (ci->ifa_valid == INFINITY)
				tprintf("valid lft(forever)");
			else
				tprintf("valid lft(%us)", ci->ifa_valid);

			if (ci->ifa_prefered == INFINITY)
				tprintf(", prefrd lft(forever)");
			else
				tprintf(", prefrd lft(%us)", ci->ifa_prefered);

			tprintf(", created on(%.2fs)", (double)ci->cstamp / 100);
			tprintf(", updated on(%.2fs))", (double)ci->cstamp / 100);
			tprintf(", Len %lu\n", RTA_LEN(attr));
			break;
		}
	}
}
Ejemplo n.º 28
0
int print_neigh(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
{
	FILE *fp = (FILE*)arg;
	struct ndmsg *r = NLMSG_DATA(n);
	int len = n->nlmsg_len;
	struct rtattr * tb[NDA_MAX+1];
	char abuf[256];

	if (n->nlmsg_type != RTM_NEWNEIGH && n->nlmsg_type != RTM_DELNEIGH) {
		fprintf(stderr, "Not RTM_NEWNEIGH: %08x %08x %08x\n",
			n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);

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

	if (filter.flushb && n->nlmsg_type != RTM_NEWNEIGH)
		return 0;

	if (filter.family && filter.family != r->ndm_family)
		return 0;
	if (filter.index && filter.index != r->ndm_ifindex)
		return 0;
	if (!(filter.state&r->ndm_state) &&
	    (r->ndm_state || !(filter.state&0x100)) &&
             (r->ndm_family != AF_DECnet))
		return 0;

	parse_rtattr(tb, NDA_MAX, NDA_RTA(r), n->nlmsg_len - NLMSG_LENGTH(sizeof(*r)));

	if (tb[NDA_DST]) {
		if (filter.pfx.family) {
			inet_prefix dst;
			memset(&dst, 0, sizeof(dst));
			dst.family = r->ndm_family;
			memcpy(&dst.data, RTA_DATA(tb[NDA_DST]), RTA_PAYLOAD(tb[NDA_DST]));
			if (inet_addr_match(&dst, &filter.pfx, filter.pfx.bitlen))
				return 0;
		}
	}
	if (filter.unused_only && tb[NDA_CACHEINFO]) {
		struct nda_cacheinfo *ci = RTA_DATA(tb[NDA_CACHEINFO]);
		if (ci->ndm_refcnt)
			return 0;
	}

	if (filter.flushb) {
		struct nlmsghdr *fn;
		if (NLMSG_ALIGN(filter.flushp) + n->nlmsg_len > filter.flushe) {
			if (flush_update())
				return -1;
		}
		fn = (struct nlmsghdr*)(filter.flushb + NLMSG_ALIGN(filter.flushp));
		memcpy(fn, n, n->nlmsg_len);
		fn->nlmsg_type = RTM_DELNEIGH;
		fn->nlmsg_flags = NLM_F_REQUEST;
		fn->nlmsg_seq = ++rth.seq;
		filter.flushp = (((char*)fn) + n->nlmsg_len) - filter.flushb;
		filter.flushed++;
		if (show_stats < 2)
			return 0;
	}

	if (tb[NDA_DST]) {
		fprintf(fp, "%s ",
			format_host(r->ndm_family,
				    RTA_PAYLOAD(tb[NDA_DST]),
				    RTA_DATA(tb[NDA_DST]),
				    abuf, sizeof(abuf)));
	}
	if (!filter.index && r->ndm_ifindex)
		fprintf(fp, "dev %s ", ll_index_to_name(r->ndm_ifindex));
	if (tb[NDA_LLADDR]) {
		SPRINT_BUF(b1);
		fprintf(fp, "lladdr %s", ll_addr_n2a(RTA_DATA(tb[NDA_LLADDR]),
					      RTA_PAYLOAD(tb[NDA_LLADDR]),
					      ll_index_to_type(r->ndm_ifindex),
					      b1, sizeof(b1)));
	}
	if (r->ndm_flags & NTF_ROUTER) {
		fprintf(fp, " router");
	}
	if (tb[NDA_CACHEINFO] && show_stats) {
		struct nda_cacheinfo *ci = RTA_DATA(tb[NDA_CACHEINFO]);
		int hz = get_user_hz();

		if (ci->ndm_refcnt)
			printf(" ref %d", ci->ndm_refcnt);
		fprintf(fp, " used %d/%d/%d", ci->ndm_used/hz,
		       ci->ndm_confirmed/hz, ci->ndm_updated/hz);
	}

	if (tb[NDA_PROBES] && show_stats) {
		__u32 p = *(__u32 *) RTA_DATA(tb[NDA_PROBES]);
		fprintf(fp, " probes %u", p);
	}

	if (r->ndm_state) {
		int nud = r->ndm_state;
		fprintf(fp, " ");

#define PRINT_FLAG(f) if (nud & NUD_##f) { \
	nud &= ~NUD_##f; fprintf(fp, #f "%s", nud ? "," : ""); }
		PRINT_FLAG(INCOMPLETE);
		PRINT_FLAG(REACHABLE);
		PRINT_FLAG(STALE);
		PRINT_FLAG(DELAY);
		PRINT_FLAG(PROBE);
		PRINT_FLAG(FAILED);
		PRINT_FLAG(NOARP);
		PRINT_FLAG(PERMANENT);
#undef PRINT_FLAG
	}
	fprintf(fp, "\n");

	fflush(fp);
	return 0;
}
Ejemplo n.º 29
0
static void rtnl_print_neigh(struct nlmsghdr *hdr)
{
	struct ndmsg *ndm = NLMSG_DATA(hdr);
	uint32_t attrs_len = NDA_PAYLOAD(hdr);
	struct rtattr *attr = NDA_RTA(ndm);
	struct nda_cacheinfo *ci;
	int hz = get_user_hz();
	char addr_str[256];
	char hw_addr[30];
	char states[256];
	char flags[256];

	tprintf(" [ Neigh Family %d (%s%s%s)", ndm->ndm_family,
			colorize_start(bold),
			addr_family2str(ndm->ndm_family),
			colorize_end());
	tprintf(", Link Index %d", ndm->ndm_ifindex);
	tprintf(", State %d (%s%s%s)", ndm->ndm_state,
			colorize_start(bold),
			flags2str(neigh_states, ndm->ndm_state, states,
				sizeof(states)),
			colorize_end());
	tprintf(", Flags %d (%s%s%s)", ndm->ndm_flags,
			colorize_start(bold),
			flags2str(neigh_flags, ndm->ndm_flags, flags,
				sizeof(flags)),
			colorize_end());
	tprintf(", Type %d (%s%s%s)", ndm->ndm_type,
			colorize_start(bold),
			route_type2str(ndm->ndm_type),
			colorize_end());
	tprintf(" ]\n");

	for (; RTA_OK(attr, attrs_len); attr = RTA_NEXT(attr, attrs_len)) {
		switch (attr->rta_type) {
		case NDA_DST:
			attr_fmt(attr, "Address %s", addr2str(ndm->ndm_family,
						RTA_DATA(attr), addr_str,
						sizeof(addr_str)));
			break;
		case NDA_LLADDR:
			attr_fmt(attr, "HW Address %s",
					device_addr2str(RTA_DATA(attr),
						RTA_LEN(attr), 0, hw_addr,
						sizeof(hw_addr)));
			break;
		case NDA_PROBES:
			attr_fmt(attr, "Probes %d", RTA_UINT32(attr));
			break;
		case NDA_CACHEINFO:
			ci = RTA_DATA(attr);
			tprintf("\tA: Cache (");
			tprintf("confirmed(%ds)", ci->ndm_confirmed / hz);
			tprintf(", used(%ds)", ci->ndm_used / hz);
			tprintf(", updated(%ds)", ci->ndm_updated / hz);
			tprintf(", refcnt(%d))", ci->ndm_refcnt);
			tprintf(", Len %lu\n", RTA_LEN(attr));
			break;
		}
	}
}
int print_linkinfo(const struct sockaddr_nl *who,
		   struct nlmsghdr *n, void *arg)
{
	FILE *fp = (FILE*)arg;
	struct ifinfomsg *ifi = NLMSG_DATA(n);
	struct rtattr * tb[IFLA_MAX+1];
	int len = n->nlmsg_len;
	unsigned m_flag = 0;

	if (n->nlmsg_type != RTM_NEWLINK && n->nlmsg_type != RTM_DELLINK)
		return 0;

	len -= NLMSG_LENGTH(sizeof(*ifi));
	if (len < 0)
		return -1;

	if (filter.ifindex && ifi->ifi_index != filter.ifindex)
		return 0;
	if (filter.up && !(ifi->ifi_flags&IFF_UP))
		return 0;

	parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
	if (tb[IFLA_IFNAME] == NULL) {
		fprintf(stderr, "BUG: device with ifindex %d has nil ifname\n", ifi->ifi_index);
	}
	if (filter.label &&
	    (!filter.family || filter.family == AF_PACKET) &&
	    fnmatch(filter.label, RTA_DATA(tb[IFLA_IFNAME]), 0))
		return 0;

	if (n->nlmsg_type == RTM_DELLINK)
		fprintf(fp, "Deleted ");

	fprintf(fp, "%d: %s", ifi->ifi_index,
		tb[IFLA_IFNAME] ? (char*)RTA_DATA(tb[IFLA_IFNAME]) : "<nil>");

	if (tb[IFLA_LINK]) {
		SPRINT_BUF(b1);
		int iflink = *(int*)RTA_DATA(tb[IFLA_LINK]);
		if (iflink == 0)
			fprintf(fp, "@NONE: ");
		else {
			fprintf(fp, "@%s: ", ll_idx_n2a(iflink, b1));
			m_flag = ll_index_to_flags(iflink);
			m_flag = !(m_flag & IFF_UP);
		}
	} else {
		fprintf(fp, ": ");
	}
	print_link_flags(fp, ifi->ifi_flags, m_flag);

	if (tb[IFLA_MTU])
		fprintf(fp, "mtu %u ", *(int*)RTA_DATA(tb[IFLA_MTU]));
	if (tb[IFLA_QDISC])
		fprintf(fp, "qdisc %s ", (char*)RTA_DATA(tb[IFLA_QDISC]));
#ifdef IFLA_MASTER
	if (tb[IFLA_MASTER]) {
		SPRINT_BUF(b1);
		fprintf(fp, "master %s ", ll_idx_n2a(*(int*)RTA_DATA(tb[IFLA_MASTER]), b1));
	}
#endif
	if (tb[IFLA_OPERSTATE])
		print_operstate(fp, *(__u8 *)RTA_DATA(tb[IFLA_OPERSTATE]));
		
	if (filter.showqueue)
		print_queuelen(fp, (char*)RTA_DATA(tb[IFLA_IFNAME]));

	if (!filter.family || filter.family == AF_PACKET) {
		SPRINT_BUF(b1);
		fprintf(fp, "%s", _SL_);
		fprintf(fp, "    link/%s ", ll_type_n2a(ifi->ifi_type, b1, sizeof(b1)));

		if (tb[IFLA_ADDRESS]) {
			fprintf(fp, "%s", ll_addr_n2a(RTA_DATA(tb[IFLA_ADDRESS]),
						      RTA_PAYLOAD(tb[IFLA_ADDRESS]),
						      ifi->ifi_type,
						      b1, sizeof(b1)));
		}
		if (tb[IFLA_BROADCAST]) {
			if (ifi->ifi_flags&IFF_POINTOPOINT)
				fprintf(fp, " peer ");
			else
				fprintf(fp, " brd ");
			fprintf(fp, "%s", ll_addr_n2a(RTA_DATA(tb[IFLA_BROADCAST]),
						      RTA_PAYLOAD(tb[IFLA_BROADCAST]),
						      ifi->ifi_type,
						      b1, sizeof(b1)));
		}
	}

	if (do_link && tb[IFLA_LINKINFO] && show_details)
		print_linktype(fp, tb[IFLA_LINKINFO]);

	if (do_link && tb[IFLA_IFALIAS])
		fprintf(fp,"\n    alias %s", 
			(const char *) RTA_DATA(tb[IFLA_IFALIAS]));

	if (do_link && tb[IFLA_STATS64] && show_stats) {
		struct rtnl_link_stats64 slocal;
		struct rtnl_link_stats64 *s = RTA_DATA(tb[IFLA_STATS64]);
		if (((unsigned long)s) & (sizeof(unsigned long)-1)) {
			memcpy(&slocal, s, sizeof(slocal));
			s = &slocal;
		}
		fprintf(fp, "%s", _SL_);
		fprintf(fp, "    RX: bytes  packets  errors  dropped overrun mcast   %s%s",
			s->rx_compressed ? "compressed" : "", _SL_);
		fprintf(fp, "    %-10llu %-8llu %-7llu %-7llu %-7llu %-7llu",
			(unsigned long long)s->rx_bytes,
			(unsigned long long)s->rx_packets,
			(unsigned long long)s->rx_errors,
			(unsigned long long)s->rx_dropped,
			(unsigned long long)s->rx_over_errors,
			(unsigned long long)s->multicast);
		if (s->rx_compressed)
			fprintf(fp, " %-7llu",
				(unsigned long long)s->rx_compressed);
		if (show_stats > 1) {
			fprintf(fp, "%s", _SL_);
			fprintf(fp, "    RX errors: length  crc     frame   fifo    missed%s", _SL_);
			fprintf(fp, "               %-7llu  %-7llu %-7llu %-7llu %-7llu",
				(unsigned long long)s->rx_length_errors,
				(unsigned long long)s->rx_crc_errors,
				(unsigned long long)s->rx_frame_errors,
				(unsigned long long)s->rx_fifo_errors,
				(unsigned long long)s->rx_missed_errors);
		}
		fprintf(fp, "%s", _SL_);
		fprintf(fp, "    TX: bytes  packets  errors  dropped carrier collsns %s%s",
			s->tx_compressed ? "compressed" : "", _SL_);
		fprintf(fp, "    %-10llu %-8llu %-7llu %-7llu %-7llu %-7llu",
			(unsigned long long)s->tx_bytes,
			(unsigned long long)s->tx_packets,
			(unsigned long long)s->tx_errors,
			(unsigned long long)s->tx_dropped,
			(unsigned long long)s->tx_carrier_errors,
			(unsigned long long)s->collisions);
		if (s->tx_compressed)
			fprintf(fp, " %-7llu",
				(unsigned long long)s->tx_compressed);
		if (show_stats > 1) {
			fprintf(fp, "%s", _SL_);
			fprintf(fp, "    TX errors: aborted fifo    window  heartbeat%s", _SL_);
			fprintf(fp, "               %-7llu  %-7llu %-7llu %-7llu",
				(unsigned long long)s->tx_aborted_errors,
				(unsigned long long)s->tx_fifo_errors,
				(unsigned long long)s->tx_window_errors,
				(unsigned long long)s->tx_heartbeat_errors);
		}
	}
	if (do_link && !tb[IFLA_STATS64] && tb[IFLA_STATS] && show_stats) {
		struct rtnl_link_stats slocal;
		struct rtnl_link_stats *s = RTA_DATA(tb[IFLA_STATS]);
		if (((unsigned long)s) & (sizeof(unsigned long)-1)) {
			memcpy(&slocal, s, sizeof(slocal));
			s = &slocal;
		}
		fprintf(fp, "%s", _SL_);
		fprintf(fp, "    RX: bytes  packets  errors  dropped overrun mcast   %s%s",
			s->rx_compressed ? "compressed" : "", _SL_);
		fprintf(fp, "    %-10u %-8u %-7u %-7u %-7u %-7u",
			s->rx_bytes, s->rx_packets, s->rx_errors,
			s->rx_dropped, s->rx_over_errors,
			s->multicast
			);
		if (s->rx_compressed)
			fprintf(fp, " %-7u", s->rx_compressed);
		if (show_stats > 1) {
			fprintf(fp, "%s", _SL_);
			fprintf(fp, "    RX errors: length  crc     frame   fifo    missed%s", _SL_);
			fprintf(fp, "               %-7u  %-7u %-7u %-7u %-7u",
				s->rx_length_errors,
				s->rx_crc_errors,
				s->rx_frame_errors,
				s->rx_fifo_errors,
				s->rx_missed_errors
				);
		}
		fprintf(fp, "%s", _SL_);
		fprintf(fp, "    TX: bytes  packets  errors  dropped carrier collsns %s%s",
			s->tx_compressed ? "compressed" : "", _SL_);
		fprintf(fp, "    %-10u %-8u %-7u %-7u %-7u %-7u",
			s->tx_bytes, s->tx_packets, s->tx_errors,
			s->tx_dropped, s->tx_carrier_errors, s->collisions);
		if (s->tx_compressed)
			fprintf(fp, " %-7u", s->tx_compressed);
		if (show_stats > 1) {
			fprintf(fp, "%s", _SL_);
			fprintf(fp, "    TX errors: aborted fifo    window  heartbeat%s", _SL_);
			fprintf(fp, "               %-7u  %-7u %-7u %-7u",
				s->tx_aborted_errors,
				s->tx_fifo_errors,
				s->tx_window_errors,
				s->tx_heartbeat_errors
				);
		}
	}
	if (do_link && tb[IFLA_VFINFO_LIST] && tb[IFLA_NUM_VF]) {
		struct rtattr *i, *vflist = tb[IFLA_VFINFO_LIST];
		int rem = RTA_PAYLOAD(vflist);
		for (i = RTA_DATA(vflist); RTA_OK(i, rem); i = RTA_NEXT(i, rem))
			print_vfinfo(fp, i);
	}

	fprintf(fp, "\n");
	fflush(fp);
	return 0;
}