/* Dump if address information to vty. */ static void connected_dump_vty (struct vty *vty, struct connected *connected) { struct prefix *p; /* Print interface address. */ p = connected->address; vty_out (vty, " %s ", prefix_family_str (p)); prefix_vty_out (vty, p); vty_out (vty, "/%d", p->prefixlen); /* If there is destination address, print it. */ if (connected->destination) { vty_out (vty, (CONNECTED_PEER(connected) ? " peer " : " broadcast ")); prefix_vty_out (vty, connected->destination); } if (CHECK_FLAG (connected->flags, ZEBRA_IFA_SECONDARY)) vty_out (vty, " secondary"); if (connected->label) vty_out (vty, " %s", connected->label); vty_out (vty, "%s", VTY_NEWLINE); }
/* Interface address modification. */ static int netlink_address(int cmd, int family, struct interface *ifp, struct connected *ifc) { int bytelen; struct prefix *p; struct { struct nlmsghdr n; struct ifaddrmsg ifa; char buf[NL_PKT_BUF_SIZE]; } req; struct zebra_ns *zns; if (vrf_is_backend_netns()) zns = zebra_ns_lookup((ns_id_t)ifp->vrf_id); else zns = zebra_ns_lookup(NS_DEFAULT); p = ifc->address; memset(&req, 0, sizeof req - NL_PKT_BUF_SIZE); bytelen = (family == AF_INET ? 4 : 16); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); req.n.nlmsg_flags = NLM_F_REQUEST; req.n.nlmsg_type = cmd; req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid; req.ifa.ifa_family = family; req.ifa.ifa_index = ifp->ifindex; addattr_l(&req.n, sizeof req, IFA_LOCAL, &p->u.prefix, bytelen); if (family == AF_INET) { if (CONNECTED_PEER(ifc)) { p = ifc->destination; addattr_l(&req.n, sizeof req, IFA_ADDRESS, &p->u.prefix, bytelen); } else if (cmd == RTM_NEWADDR && ifc->destination) { p = ifc->destination; addattr_l(&req.n, sizeof req, IFA_BROADCAST, &p->u.prefix, bytelen); } } /* p is now either ifc->address or ifc->destination */ req.ifa.ifa_prefixlen = p->prefixlen; if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)) SET_FLAG(req.ifa.ifa_flags, IFA_F_SECONDARY); if (ifc->label) addattr_l(&req.n, sizeof req, IFA_LABEL, ifc->label, strlen(ifc->label) + 1); return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0); }
/* Interface address modification. */ static int netlink_address (int cmd, int family, struct interface *ifp, struct connected *ifc) { int bytelen; struct prefix *p; struct { struct nlmsghdr n; struct ifaddrmsg ifa; char buf[NL_PKT_BUF_SIZE]; } req; p = ifc->address; memset (&req, 0, sizeof req); bytelen = (family == AF_INET ? 4 : 16); req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct ifaddrmsg)); req.n.nlmsg_flags = NLM_F_REQUEST; req.n.nlmsg_type = cmd; req.ifa.ifa_family = family; req.ifa.ifa_index = ifp->ifindex; req.ifa.ifa_prefixlen = p->prefixlen; addattr_l (&req.n, sizeof req, IFA_LOCAL, &p->u.prefix, bytelen); if (family == AF_INET && cmd == RTM_NEWADDR) { if (!CONNECTED_PEER(ifc) && ifc->destination) { p = ifc->destination; addattr_l (&req.n, sizeof req, IFA_BROADCAST, &p->u.prefix, bytelen); } } if (CHECK_FLAG (ifc->flags, KROUTE_IFA_SECONDARY)) SET_FLAG (req.ifa.ifa_flags, IFA_F_SECONDARY); if (ifc->label) addattr_l (&req.n, sizeof req, IFA_LABEL, ifc->label, strlen (ifc->label) + 1); return netlink_talk (&req.n, &netlink_cmd); }
/* Add connected IPv4 route to the interface. */ void connected_add_ipv4(struct interface *ifp, int flags, struct in_addr *addr, u_char prefixlen, struct in_addr *broad, const char *label) { struct prefix_ipv4 *p; struct connected *ifc; /* Make connected structure. */ ifc = connected_new(); ifc->ifp = ifp; ifc->flags = flags; /* If we get a notification from the kernel, * we can safely assume the address is known to the kernel */ SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); /* Allocate new connected address. */ p = prefix_ipv4_new(); p->family = AF_INET; p->prefix = *addr; p->prefixlen = prefixlen; ifc->address = (struct prefix *)p; /* If there is broadcast or peer address. */ if (broad) { p = prefix_ipv4_new(); p->family = AF_INET; p->prefix = *broad; p->prefixlen = prefixlen; ifc->destination = (struct prefix *)p; /* validate the destination address */ if (CONNECTED_PEER(ifc)) { if (IPV4_ADDR_SAME(addr, broad)) zlog_warn ("warning: interface %s has same local and peer " "address %s, routing protocols may malfunction", ifp->name, inet_ntoa(*addr)); } else { if (broad->s_addr != ipv4_broadcast_addr(addr->s_addr, prefixlen)) { char buf[2][INET_ADDRSTRLEN]; struct in_addr bcalc; bcalc.s_addr = ipv4_broadcast_addr(addr->s_addr, prefixlen); zlog_warn ("warning: interface %s broadcast addr %s/%d != " "calculated %s, routing protocols may malfunction", ifp->name, inet_ntop(AF_INET, broad, buf[0], sizeof(buf[0])), prefixlen, inet_ntop(AF_INET, &bcalc, buf[1], sizeof(buf[1]))); } } } else { if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER)) { zlog_warn("warning: %s called for interface %s " "with peer flag set, but no peer address supplied", __func__, ifp->name); UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER); } /* no broadcast or destination address was supplied */ if ((prefixlen == IPV4_MAX_PREFIXLEN) && if_is_pointopoint(ifp)) zlog_warn ("warning: PtP interface %s with addr %s/%d needs a " "peer address", ifp->name, inet_ntoa(*addr), prefixlen); } /* Label of this address. */ if (label) ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label); /* For all that I know an IPv4 address is always ready when we receive * the notification. So it should be safe to set the REAL flag here. */ SET_FLAG(ifc->conf, ZEBRA_IFC_REAL); connected_update(ifp, ifc); }
/* Add connected IPv4 route to the interface. */ void connected_add_ipv4 (struct interface *ifp, int flags, struct in_addr *addr, u_char prefixlen, struct in_addr *broad, const char *label) { struct prefix_ipv4 *p; struct connected *ifc; /* Make connected structure. */ ifc = connected_new (); ifc->ifp = ifp; ifc->flags = flags; /* Allocate new connected address. */ p = prefix_ipv4_new (); p->family = AF_INET; p->prefix = *addr; p->prefixlen = prefixlen; ifc->address = (struct prefix *) p; /* If there is broadcast or peer address. */ if (broad) { p = prefix_ipv4_new (); p->family = AF_INET; p->prefix = *broad; p->prefixlen = prefixlen; ifc->destination = (struct prefix *) p; /* validate the destination address */ if (CONNECTED_PEER(ifc)) { if (IPV4_ADDR_SAME(addr,broad)) zlog_warn("warning: interface %s has same local and peer " "address %s, routing protocols may malfunction", ifp->name,inet_ntoa(*addr)); } else { if (broad->s_addr != ipv4_broadcast_addr(addr->s_addr,prefixlen)) { char buf[2][INET_ADDRSTRLEN]; struct in_addr bcalc; bcalc.s_addr = ipv4_broadcast_addr(addr->s_addr,prefixlen); zlog_warn("warning: interface %s broadcast addr %s/%d != " "calculated %s, routing protocols may malfunction", ifp->name, inet_ntop (AF_INET, broad, buf[0], sizeof(buf[0])), prefixlen, inet_ntop (AF_INET, &bcalc, buf[1], sizeof(buf[1]))); } } } else { if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER)) { zlog_warn("warning: %s called for interface %s " "with peer flag set, but no peer address supplied", __func__, ifp->name); UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER); } /* no broadcast or destination address was supplied */ if ((prefixlen == IPV4_MAX_PREFIXLEN) && if_is_pointopoint(ifp)) zlog_warn("warning: PtP interface %s with addr %s/%d needs a " "peer address",ifp->name,inet_ntoa(*addr),prefixlen); } /* Label of this address. */ if (label) ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label); /* nothing to do? */ if ((ifc = connected_implicit_withdraw (ifp, ifc)) == NULL) return; connected_announce (ifp, ifc); }