Beispiel #1
0
static int neigh_mod(int nl_flags, int cmd, int ifindex,
		     uint16_t state, uint8_t flags, struct in6_addr *dst,
		     uint8_t *hwa, int hwalen)
{
	uint8_t buf[256];
	struct nlmsghdr *n;
	struct ndmsg *ndm;

	memset(buf, 0, sizeof(buf));
	n = (struct nlmsghdr *)buf;
	n->nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
	n->nlmsg_flags = NLM_F_REQUEST|nl_flags;
	n->nlmsg_type = cmd;

        ndm = NLMSG_DATA(n);
	ndm->ndm_family = AF_INET6;
	ndm->ndm_ifindex = ifindex;
	ndm->ndm_state = state;
	ndm->ndm_flags = flags;
	ndm->ndm_type = (IN6_IS_ADDR_MULTICAST(dst) ? 
			 RTN_MULTICAST : RTN_UNICAST);

	addattr_l(n, sizeof(buf), NDA_DST, dst, sizeof(*dst));

	if (hwa)
		addattr_l(n, sizeof(buf), NDA_LLADDR, hwa, hwalen);

	return rtnl_route_do(n, NULL);
}
int prefix_add(int ifindex, const struct nd_opt_prefix_info *pinfo)
{
	uint8_t buf[128];
	struct nlmsghdr *n;
	struct prefixmsg *pfxm;
	struct prefix_cacheinfo ci;

	memset(buf, 0, sizeof(buf));
	n = (struct nlmsghdr *)buf;
	n->nlmsg_len = NLMSG_LENGTH(sizeof(struct prefixmsg));
	n->nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE|NLM_F_REPLACE;
	n->nlmsg_type = RTM_NEWPREFIX;

	pfxm = NLMSG_DATA(n);
	pfxm->prefix_family = AF_INET6;
	pfxm->prefix_ifindex = ifindex;
	pfxm->prefix_type = pinfo->nd_opt_pi_type;
	pfxm->prefix_len = pinfo->nd_opt_pi_prefix_len;
	pfxm->prefix_flags = pinfo->nd_opt_pi_flags_reserved;

	addattr_l(n, sizeof(buf), PREFIX_ADDRESS, &pinfo->nd_opt_pi_prefix,
		  sizeof(struct in6_addr));
	memset(&ci, 0, sizeof(ci));
	/* pinfo lifetimes stored locally in host byte order */
	ci.valid_time = htonl(pinfo->nd_opt_pi_valid_time);
	ci.preferred_time = htonl(pinfo->nd_opt_pi_preferred_time);
	addattr_l(n, sizeof(buf), PREFIX_CACHEINFO, &ci, sizeof(ci));

	return rtnl_route_do(n, NULL);
}
static int addr_mod(int cmd, uint16_t nlmsg_flags,
		    const struct in6_addr *addr, uint8_t plen,
		    uint8_t flags, uint8_t scope, int ifindex,
		    uint32_t prefered, uint32_t valid)

{
	uint8_t buf[256];
	struct nlmsghdr *n;
	struct ifaddrmsg *ifa;

	memset(buf, 0, sizeof(buf));
	n = (struct nlmsghdr *)buf;
	n->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
	n->nlmsg_flags = NLM_F_REQUEST | nlmsg_flags;
	n->nlmsg_type = cmd;

	ifa = NLMSG_DATA(n);
	ifa->ifa_family = AF_INET6;
	ifa->ifa_prefixlen = plen;
	ifa->ifa_flags = flags;
	ifa->ifa_scope = scope;
	ifa->ifa_index = ifindex;

	addattr_l(n, sizeof(buf), IFA_LOCAL, addr, sizeof(*addr));

	if (prefered || valid) {
		struct ifa_cacheinfo ci;
		ci.ifa_prefered = prefered;
		ci.ifa_valid = valid;
		ci.cstamp = 0;
		ci.tstamp = 0;
		addattr_l(n, sizeof(buf), IFA_CACHEINFO, &ci, sizeof(ci));
	}
	return rtnl_route_do(n, NULL);
}
int addr_do(const struct in6_addr *addr, int plen, int ifindex, void *arg,
	    int (*do_callback)(struct ifaddrmsg *ifa,
			       struct rtattr *rta_tb[], void *arg))
{
	uint8_t sbuf[256];
	uint8_t rbuf[256];
	struct nlmsghdr *sn, *rn;
	struct ifaddrmsg *ifa;
	int err;
	struct rtattr *rta_tb[IFA_MAX+1];

	memset(sbuf, 0, sizeof(sbuf));
	sn = (struct nlmsghdr *)sbuf;
	sn->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
	sn->nlmsg_flags = NLM_F_REQUEST;
	sn->nlmsg_type = RTM_GETADDR;

	ifa = NLMSG_DATA(sn);
	ifa->ifa_family = AF_INET6;
	ifa->ifa_prefixlen = plen;
	ifa->ifa_scope = RT_SCOPE_UNIVERSE;
	ifa->ifa_index = ifindex;

	addattr_l(sn, sizeof(sbuf), IFA_LOCAL, addr, sizeof(*addr));

	memset(rbuf, 0, sizeof(rbuf));
	rn = (struct nlmsghdr *)rbuf;
	err = rtnl_route_do(sn, rn);
	if (err < 0) {
		rn = sn;
		ifa = NLMSG_DATA(rn);
	} else {
		ifa = NLMSG_DATA(rn);

		if (rn->nlmsg_type != RTM_NEWADDR ||
		    rn->nlmsg_len < NLMSG_LENGTH(sizeof(*ifa)) ||
		    ifa->ifa_family != AF_INET6) {
			return -EINVAL;
		}
	}
	memset(rta_tb, 0, sizeof(rta_tb));
	parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(ifa),
		     rn->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa)));

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

	if (!rta_tb[IFA_ADDRESS] ||
	    !IN6_ARE_ADDR_EQUAL(RTA_DATA(rta_tb[IFA_ADDRESS]), addr)) {
		return -EINVAL;
	}
	if (do_callback)
		err = do_callback(ifa, rta_tb, arg);

	return err;

}
static int route_mod(int cmd, int oif, uint8_t table, uint8_t proto,
		     unsigned flags, uint32_t priority,
		     const struct in6_addr *src, int src_plen,
		     const struct in6_addr *dst, int dst_plen,
		     const struct in6_addr *gateway)
{
	uint8_t buf[512];
	struct nlmsghdr *n;
	struct rtmsg *rtm;

	if (cmd == RTM_NEWROUTE && oif == 0)
		return -1;

	memset(buf, 0, sizeof(buf));
	n = (struct nlmsghdr *)buf;

	n->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
	n->nlmsg_flags = NLM_F_REQUEST;
	if (cmd == RTM_NEWROUTE) {
		n->nlmsg_flags |= NLM_F_CREATE|NLM_F_EXCL;
	}
	n->nlmsg_type = cmd;

	rtm = NLMSG_DATA(n);
	rtm->rtm_family = AF_INET6;
	rtm->rtm_dst_len = dst_plen;
	rtm->rtm_src_len = src_plen;
	rtm->rtm_table = table;
	rtm->rtm_protocol = proto;
	rtm->rtm_scope = RT_SCOPE_UNIVERSE;
	rtm->rtm_type = RTN_UNICAST;
	rtm->rtm_flags = flags;

	addattr_l(n, sizeof(buf), RTA_DST, dst, sizeof(*dst));
	if (src)
		addattr_l(n, sizeof(buf), RTA_SRC, src, sizeof(*src));
	addattr32(n, sizeof(buf), RTA_OIF, oif);
	if (gateway)
		addattr_l(n, sizeof(buf),
			  RTA_GATEWAY, gateway, sizeof(*gateway));
	if (priority)
		addattr32(n, sizeof(buf), RTA_PRIORITY, priority);
	return rtnl_route_do(n, NULL);
}
static int rule_mod(const char *iface, int cmd, uint8_t table,
		    uint32_t priority, uint8_t action,
		    const struct in6_addr *src, int src_plen,
		    const struct in6_addr *dst, int dst_plen, int flags)
{
	uint8_t buf[512];
	struct nlmsghdr *n;
	struct rtmsg *rtm;

	memset(buf, 0, sizeof(buf));
	n = (struct nlmsghdr *)buf;

	n->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
	n->nlmsg_flags = NLM_F_REQUEST;
	if (cmd == RTM_NEWRULE) {
		n->nlmsg_flags |= NLM_F_CREATE;
	}
	n->nlmsg_type = cmd;

	rtm = NLMSG_DATA(n);
	rtm->rtm_family = AF_INET6;
	rtm->rtm_dst_len = dst_plen;
	rtm->rtm_src_len = src_plen;
	rtm->rtm_table = table;
	rtm->rtm_scope = RT_SCOPE_UNIVERSE;
	rtm->rtm_type = action;
	rtm->rtm_flags = flags;

	addattr_l(n, sizeof(buf), RTA_DST, dst, sizeof(*dst));
	if (src)
		addattr_l(n, sizeof(buf), RTA_SRC, src, sizeof(*src));
	if (priority)
		addattr32(n, sizeof(buf), RTA_PRIORITY, priority);
	if (iface)
		addattr_l(n, sizeof(buf), RTA_IIF, iface, strlen(iface) + 1);

	return rtnl_route_do(n, NULL);
}