#include "zebra/debug.h"
#include "zebra/irdp.h"
#include "zebra/zebra_ptm.h"
+#include "zebra/rt_netlink.h"
#define ZEBRA_PTM_SUPPORT
ifp->ifindex = IFINDEX_INTERNAL;
}
+void
+ipv6_ll_address_to_mac (struct in6_addr *address, u_char *mac)
+{
+ mac[0] = address->s6_addr[8];
+ mac[0] &= ~0x02;
+ mac[1] = address->s6_addr[9];
+ mac[2] = address->s6_addr[10];
+ mac[3] = address->s6_addr[13];
+ mac[4] = address->s6_addr[14];
+ mac[5] = address->s6_addr[15];
+}
+
+void
+if_nbr_ipv6ll_to_ipv4ll_neigh_update (struct interface *ifp,
+ struct in6_addr *address,
+ int add)
+{
+ char buf[16] = "169.254.0.1";
+ struct in_addr ipv4_ll;
+ u_char mac[6];
+
+ inet_pton (AF_INET, buf, &ipv4_ll);
+
+ ipv6_ll_address_to_mac(address, mac);
+ netlink_neigh_update (add ? RTM_NEWNEIGH : RTM_DELNEIGH,
+ ifp->ifindex, ipv4_ll.s_addr, mac, 6);
+}
+
+void
+if_nbr_ipv6ll_to_ipv4ll_neigh_add_all (struct interface *ifp)
+{
+ if (listhead(ifp->nbr_connected))
+ {
+ struct nbr_connected *nbr_connected;
+ struct listnode *node;
+
+ for (ALL_LIST_ELEMENTS_RO (ifp->nbr_connected, node, nbr_connected))
+ if_nbr_ipv6ll_to_ipv4ll_neigh_update (ifp,
+ &nbr_connected->address->u.prefix6,
+ 1);
+ }
+}
+
+void
+if_nbr_ipv6ll_to_ipv4ll_neigh_del_all (struct interface *ifp)
+{
+ if (listhead(ifp->nbr_connected))
+ {
+ struct nbr_connected *nbr_connected;
+ struct listnode *node;
+
+ for (ALL_LIST_ELEMENTS_RO (ifp->nbr_connected, node, nbr_connected))
+ if_nbr_ipv6ll_to_ipv4ll_neigh_update (ifp,
+ &nbr_connected->address->u.prefix6,
+ 0);
+ }
+}
+
/* Interface is up. */
void
if_up (struct interface *ifp)
}
zebra_interface_up_update (ifp);
+ if_nbr_ipv6ll_to_ipv4ll_neigh_add_all (ifp);
/* Install connected routes to the kernel. */
if (ifp->connected)
/* Examine all static routes which direct to the interface. */
rib_update ();
+
+ if_nbr_ipv6ll_to_ipv4ll_neigh_del_all (ifp);
}
void
#endif /* SUNOS_5 */
};
+extern void if_nbr_ipv6ll_to_ipv4ll_neigh_update (struct interface *ifp,
+ struct in6_addr *address, int add);
+extern void if_nbr_ipv6ll_to_ipv4ll_neigh_del_all (struct interface *ifp);
extern void if_delete_update (struct interface *ifp);
extern void if_add_update (struct interface *ifp);
extern void if_up (struct interface *);
return 0;
}
+int netlink_neigh_update (int cmd, int ifindex, __u32 addr, char *lla, int llalen)
+{
+ return 0;
+}
+
void kernel_init (void) { return; }
#ifdef HAVE_SYS_WEAK_ALIAS_PRAGMA
#pragma weak route_read = kernel_init
size_t req_size,
int cmd)
{
+
+ if (rtmsg->rtm_family == AF_INET &&
+ (nexthop->type == NEXTHOP_TYPE_IPV6
+ || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
+ || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX))
+ {
+ char buf[16] = "169.254.0.1";
+ struct in_addr ipv4_ll;
+
+ inet_pton (AF_INET, buf, &ipv4_ll);
+ rtmsg->rtm_flags |= RTNH_F_ONLINK;
+ addattr_l (nlmsg, req_size, RTA_GATEWAY, &ipv4_ll, 4);
+ addattr32 (nlmsg, req_size, RTA_OIF, nexthop->ifindex);
+
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug(" 5549: _netlink_route_build_singlepath() (%s): "
+ "nexthop via %s if %u",
+ routedesc, buf, nexthop->ifindex);
+ return;
+ }
+
if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK))
rtmsg->rtm_flags |= RTNH_F_ONLINK;
+
if (nexthop->type == NEXTHOP_TYPE_IPV4
|| nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
{
struct nexthop *nexthop,
struct rtattr *rta,
struct rtnexthop *rtnh,
- union g_addr **src
- )
+ struct rtmsg *rtmsg,
+ union g_addr **src)
{
rtnh->rtnh_len = sizeof (*rtnh);
rtnh->rtnh_flags = 0;
rtnh->rtnh_hops = 0;
rta->rta_len += rtnh->rtnh_len;
+ if (rtmsg->rtm_family == AF_INET &&
+ (nexthop->type == NEXTHOP_TYPE_IPV6
+ || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
+ || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX))
+ {
+ char buf[16] = "169.254.0.1";
+ struct in_addr ipv4_ll;
+
+ inet_pton (AF_INET, buf, &ipv4_ll);
+ bytelen = 4;
+ rtnh->rtnh_flags |= RTNH_F_ONLINK;
+ rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTA_GATEWAY,
+ &ipv4_ll, bytelen);
+ rtnh->rtnh_len += sizeof (struct rtattr) + bytelen;
+ rtnh->rtnh_ifindex = nexthop->ifindex;
+
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug(" 5549: netlink_route_build_multipath() (%s): "
+ "nexthop via %s if %u",
+ routedesc, buf, nexthop->ifindex);
+ return;
+ }
+
+
if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK))
rtnh->rtnh_flags |= RTNH_F_ONLINK;
}
}
+int
+netlink_neigh_update (int cmd, int ifindex, __u32 addr, char *lla, int llalen)
+{
+ struct {
+ struct nlmsghdr n;
+ struct ndmsg ndm;
+ char buf[256];
+ } req;
+
+ memset(&req.n, 0, sizeof(req.n));
+ memset(&req.ndm, 0, sizeof(req.ndm));
+
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
+ req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
+ req.n.nlmsg_type = cmd; //RTM_NEWNEIGH or RTM_DELNEIGH
+ req.ndm.ndm_family = AF_INET;
+ req.ndm.ndm_state = NUD_PERMANENT;
+ req.ndm.ndm_ifindex = ifindex;
+ req.ndm.ndm_type = RTN_UNICAST;
+
+ addattr_l(&req.n, sizeof(req), NDA_DST, &addr, 4);
+ addattr_l(&req.n, sizeof(req), NDA_LLADDR, lla, llalen);
+
+ return netlink_talk (&req.n, &netlink_cmd);
+}
+
/* Routing table change via netlink interface. */
/* Update flag indicates whether this is a "replace" or not. */
static int
_netlink_route_debug(cmd, p, nexthop,
routedesc, family);
_netlink_route_build_multipath(routedesc, bytelen,
- nexthop, rta, rtnh, &src1);
+ nexthop, rta, rtnh, &req.r, &src1);
rtnh = RTNH_NEXT (rtnh);
if (cmd == RTM_NEWROUTE)
extern const char *
nl_rtproto_to_str (u_char rtproto);
+int
+netlink_neigh_update (int cmd, int ifindex, __u32 addr, char *lla, int llalen);
+
extern int netlink_route_read(void);
extern int interface_lookup_netlink(void);
void
rib_close (void)
{
+ struct listnode *node, *nnode;
+ struct interface *ifp;
+
rib_close_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
rib_close_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
+
+ for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
+ if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(ifp);
}
/* Routing information base initialize. */
#include "zebra/debug.h"
#include "zebra/ipforward.h"
#include "zebra/zebra_rnh.h"
+#include "zebra/rt_netlink.h"
/* Event list of zebra. */
enum event { ZEBRA_SERV, ZEBRA_READ, ZEBRA_WRITE };
prefix_copy(ifc->address, &p);
zebra_interface_nbr_address_add_update (ifp, ifc);
+
+ if_nbr_ipv6ll_to_ipv4ll_neigh_update (ifp, address, 1);
}
void
zebra_interface_nbr_address_delete_update (ifp, ifc);
+ if_nbr_ipv6ll_to_ipv4ll_neigh_update (ifp, address, 0);
+
nbr_connected_free (ifc);
}