315
343
rta = (struct rtattr *) IFA_RTA(ifa);
316
344
len = NLMSG_PAYLOAD(nlm, sizeof(*ifa));
317
addr.s_addr = dest.s_addr = INADDR_ANY;
318
dest.s_addr = INADDR_ANY;
319
inet_cidrtoaddr(ifa->ifa_prefixlen, &net);
320
while (RTA_OK(rta, len)) {
321
switch (rta->rta_type) {
323
if (iface->flags & IFF_POINTOPOINT) {
324
memcpy(&dest.s_addr, RTA_DATA(rta),
325
sizeof(addr.s_addr));
329
memcpy(&addr.s_addr, RTA_DATA(rta),
330
sizeof(addr.s_addr));
333
rta = RTA_NEXT(rta, len);
345
switch (ifa->ifa_family) {
348
addr.s_addr = dest.s_addr = INADDR_ANY;
349
dest.s_addr = INADDR_ANY;
350
inet_cidrtoaddr(ifa->ifa_prefixlen, &net);
351
while (RTA_OK(rta, len)) {
352
switch (rta->rta_type) {
354
if (iface->flags & IFF_POINTOPOINT) {
355
memcpy(&dest.s_addr, RTA_DATA(rta),
356
sizeof(addr.s_addr));
360
memcpy(&addr.s_addr, RTA_DATA(rta),
361
sizeof(addr.s_addr));
364
rta = RTA_NEXT(rta, len);
366
ipv4_handleifa(nlm->nlmsg_type, ifn, &addr, &net, &dest);
371
memset(&addr6, 0, sizeof(addr6));
372
while (RTA_OK(rta, len)) {
373
switch (rta->rta_type) {
375
memcpy(&addr6.s6_addr, RTA_DATA(rta),
376
sizeof(addr6.s6_addr));
379
rta = RTA_NEXT(rta, len);
381
ipv6_handleifa(nlm->nlmsg_type, NULL, ifn,
382
&addr6, ifa->ifa_flags);
335
handle_ifa(nlm->nlmsg_type, ifn, &addr, &net, &dest);
389
static short l2addr_len(unsigned short if_type)
393
case ARPHRD_ETHER: /* FALLTHROUGH */
394
case ARPHRD_IEEE802: /*FALLTHROUGH */
395
case ARPHRD_IEEE80211:
397
case ARPHRD_IEEE1394:
399
case ARPHRD_INFINIBAND:
340
407
link_netlink(struct nlmsghdr *nlm)
410
struct rtattr *rta, *hwaddr;
344
411
struct ifinfomsg *ifi;
345
412
char ifn[IF_NAMESIZE + 1];
585
660
add_attr_l(&nlm->hdr, sizeof(*nlm), RTA_GATEWAY,
586
661
&rt->gate.s_addr, sizeof(rt->gate.s_addr));
588
add_attr_32(&nlm->hdr, sizeof(*nlm), RTA_OIF, ifindex);
589
add_attr_32(&nlm->hdr, sizeof(*nlm), RTA_PRIORITY, rt->metric);
591
if (send_netlink(&nlm->hdr) == -1)
663
if (rt->gate.s_addr != htonl(INADDR_LOOPBACK))
664
add_attr_32(&nlm->hdr, sizeof(*nlm), RTA_OIF, rt->iface->index);
665
add_attr_32(&nlm->hdr, sizeof(*nlm), RTA_PRIORITY, rt->metric);
667
if (send_netlink(&nlm->hdr) == -1)
676
if_address6(const struct ipv6_addr *ap, int action)
679
struct ifa_cacheinfo cinfo;
682
nlm = calloc(1, sizeof(*nlm));
685
nlm->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
686
nlm->hdr.nlmsg_flags = NLM_F_REQUEST;
688
nlm->hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE;
689
nlm->hdr.nlmsg_type = RTM_NEWADDR;
691
nlm->hdr.nlmsg_type = RTM_DELADDR;
692
nlm->ifa.ifa_index = ap->iface->index;
693
nlm->ifa.ifa_family = AF_INET6;
694
nlm->ifa.ifa_prefixlen = ap->prefix_len;
695
/* This creates the aliased interface */
696
add_attr_l(&nlm->hdr, sizeof(*nlm), IFA_LABEL,
697
ap->iface->name, strlen(ap->iface->name) + 1);
698
add_attr_l(&nlm->hdr, sizeof(*nlm), IFA_LOCAL,
699
&ap->addr.s6_addr, sizeof(ap->addr.s6_addr));
702
memset(&cinfo, 0, sizeof(cinfo));
703
cinfo.ifa_prefered = ap->prefix_pltime;
704
cinfo.ifa_valid = ap->prefix_vltime;
705
add_attr_l(&nlm->hdr, sizeof(*nlm), IFA_CACHEINFO,
706
&cinfo, sizeof(cinfo));
709
if (send_netlink(&nlm->hdr) == -1)
716
rta_add_attr_32(struct rtattr *rta, unsigned int maxlen,
717
int type, uint32_t data)
719
unsigned int len = RTA_LENGTH(sizeof(data));
720
struct rtattr *subrta;
722
if (RTA_ALIGN(rta->rta_len) + len > maxlen) {
727
subrta = (struct rtattr*)(((char*)rta) + RTA_ALIGN(rta->rta_len));
728
subrta->rta_type = type;
729
subrta->rta_len = len;
730
memcpy(RTA_DATA(subrta), &data, sizeof(data));
731
rta->rta_len = NLMSG_ALIGN(rta->rta_len) + len;
736
if_route6(const struct rt6 *rt, int action)
740
struct rtattr *metrics = (void *)metricsbuf;
743
nlm = calloc(1, sizeof(*nlm));
746
nlm->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
747
nlm->hdr.nlmsg_type = RTM_NEWROUTE;
748
nlm->hdr.nlmsg_flags = NLM_F_REQUEST;
750
nlm->hdr.nlmsg_flags |= NLM_F_REPLACE;
751
else if (action == 1)
752
nlm->hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
754
nlm->hdr.nlmsg_type = RTM_DELROUTE;
755
nlm->rt.rtm_family = AF_INET6;
756
nlm->rt.rtm_table = RT_TABLE_MAIN;
758
if (action == -1 || action == -2)
759
nlm->rt.rtm_scope = RT_SCOPE_NOWHERE;
761
nlm->hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
762
/* None interface subnet routes are static. */
763
if (IN6_IS_ADDR_UNSPECIFIED(&rt->gate)) {
764
nlm->rt.rtm_protocol = RTPROT_KERNEL;
765
nlm->rt.rtm_scope = RT_SCOPE_LINK;
767
nlm->rt.rtm_protocol = RTPROT_BOOT;
768
nlm->rt.rtm_type = RTN_UNICAST;
771
nlm->rt.rtm_dst_len = ipv6_prefixlen(&rt->net);
772
add_attr_l(&nlm->hdr, sizeof(*nlm), RTA_DST,
773
&rt->dest.s6_addr, sizeof(rt->dest.s6_addr));
775
/* If destination == gateway then don't add the gateway */
776
if (!IN6_IS_ADDR_UNSPECIFIED(&rt->gate) &&
777
!IN6_ARE_ADDR_EQUAL(&rt->dest, &rt->gate))
778
add_attr_l(&nlm->hdr, sizeof(*nlm), RTA_GATEWAY,
779
&rt->gate.s6_addr, sizeof(rt->gate.s6_addr));
781
add_attr_32(&nlm->hdr, sizeof(*nlm), RTA_OIF, rt->iface->index);
782
add_attr_32(&nlm->hdr, sizeof(*nlm), RTA_PRIORITY, rt->metric);
785
metrics->rta_type = RTA_METRICS;
786
metrics->rta_len = RTA_LENGTH(0);
787
rta_add_attr_32(metrics, sizeof(metricsbuf), RTAX_MTU, rt->mtu);
788
add_attr_l(&nlm->hdr, sizeof(*nlm), RTA_METRICS,
789
RTA_DATA(metrics), RTA_PAYLOAD(metrics));
792
if (send_netlink(&nlm->hdr) == -1)
801
in6_addr_flags(__unused const char *ifname,
802
__unused const struct in6_addr *addr)
805
/* How do I get IPv6 address flags on Linux? */