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); }