diff -Naur quagga-0.98.2/zebra/connected.c quagga-0.98.2-route-connected-fix-ipv6-fix/zebra/connected.c --- quagga-0.98.2/zebra/connected.c 2004-12-22 17:32:16.000000000 +0100 +++ quagga-0.98.2-route-connected-fix-ipv6-fix/zebra/connected.c 2005-02-23 09:59:09.916749568 +0100 @@ -29,6 +29,7 @@ #include "rib.h" #include "table.h" #include "log.h" +#include "rt.h" #include "zebra/zserv.h" #include "zebra/redistribute.h" @@ -86,6 +87,8 @@ rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0, 0, 0); rib_update (); + + kernel_connected_up(ifc); } /* Add connected IPv4 route to the interface. */ @@ -224,6 +227,8 @@ rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0); rib_update (); + + kernel_connected_down(ifc); } /* Delete connected IPv4 route to the interface. */ @@ -316,6 +321,8 @@ rib_add_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0); rib_update (); + + kernel_connected_up(ifc); } /* Add connected IPv6 route to the interface. */ @@ -405,6 +412,8 @@ rib_delete_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0); rib_update (); + + kernel_connected_down(ifc); } void diff -Naur quagga-0.98.2/zebra/rt.h quagga-0.98.2-route-connected-fix-ipv6-fix/zebra/rt.h --- quagga-0.98.2/zebra/rt.h 2002-12-13 21:15:30.000000000 +0100 +++ quagga-0.98.2-route-connected-fix-ipv6-fix/zebra/rt.h 2005-02-23 09:59:09.917749416 +0100 @@ -29,6 +29,9 @@ int kernel_address_add_ipv4 (struct interface *, struct connected *); int kernel_address_delete_ipv4 (struct interface *, struct connected *); +int kernel_connected_up (struct connected *ifc); +int kernel_connected_down (struct connected *ifc); + #ifdef HAVE_IPV6 int kernel_add_ipv6 (struct prefix *, struct rib *); int kernel_delete_ipv6 (struct prefix *, struct rib *); diff -Naur quagga-0.98.2/zebra/rt_ioctl.c quagga-0.98.2-route-connected-fix-ipv6-fix/zebra/rt_ioctl.c --- quagga-0.98.2/zebra/rt_ioctl.c 2004-12-07 22:12:56.000000000 +0100 +++ quagga-0.98.2-route-connected-fix-ipv6-fix/zebra/rt_ioctl.c 2005-02-23 09:59:09.916749568 +0100 @@ -44,6 +44,20 @@ return; } +/* Dummy function */ +int +kernel_connected_up (struct connected *ifc) +{ + return 0; +} + +/* Dummy function */ +int +kernel_connected_down (struct connected *ifc) +{ + return 0; +} + #if 0 /* Initialization prototype of struct sockaddr_in. */ static struct sockaddr_in sin_proto = diff -Naur quagga-0.98.2/zebra/rt_netlink.c quagga-0.98.2-route-connected-fix-ipv6-fix/zebra/rt_netlink.c --- quagga-0.98.2/zebra/rt_netlink.c 2004-12-07 22:12:56.000000000 +0100 +++ quagga-0.98.2-route-connected-fix-ipv6-fix/zebra/rt_netlink.c 2005-02-23 10:00:06.553139528 +0100 @@ -1329,6 +1329,112 @@ return 0; } +/* Routing table change for connected route via netlink interface. */ +int +netlink_routeconnected (int cmd, struct connected *ifc) +{ + int ret; + int bytelen; + struct sockaddr_nl snl; + u_char bufnet[BUFSIZ]; + u_char bufaddr[BUFSIZ]; + u_char bufsrc[BUFSIZ]; + + int cmds[] = { RTM_NEWROUTE, RTM_DELROUTE }; + + struct prefix *p = ifc->address; + int family = ifc->address->family; + int table = RT_TABLE_MAIN; + int index = ifc->ifp->ifindex; + + struct prefix dest; + struct prefix src; + int length = p->prefixlen; + + struct + { + struct nlmsghdr n; + struct rtmsg r; + char buf[1024]; + } req; + + if (! (index && p)) + return -1; + +#ifdef HAVE_IPV6 + if ((family == AF_INET6) && (IN6_IS_ADDR_LINKLOCAL(&p->u.prefix6))) + return -1; +#endif /* HAVE_IPV6 */ + + memset (&dest, 0, sizeof dest); + memset (&req, 0, sizeof req); + memset (&src, 0, sizeof(struct prefix)); + + /* Copy prefix */ + prefix_copy (&src, p); + prefix2str(&src, bufsrc, sizeof (bufaddr)); + + prefix_copy (&dest, p); + prefix2str(&dest, bufaddr, sizeof (bufaddr)); + + /* Make it sure prefixlen is applied to the prefix. */ + apply_mask (&dest); + prefix2str(&dest, bufnet, sizeof (bufnet)); + + bytelen = (family == AF_INET ? 4 : 16); + + req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg)); + req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST; + req.n.nlmsg_type = cmds[cmd]; + req.r.rtm_family = family; + req.r.rtm_table = table; + req.r.rtm_dst_len = length; + req.r.rtm_src_len = IPV4_MAX_BITLEN; + + req.r.rtm_protocol = RTPROT_KERNEL; + req.r.rtm_scope = RT_SCOPE_LINK; + req.r.rtm_type = RTN_UNICAST; + + addattr_l (&req.n, sizeof req, RTA_DST, &dest.u.prefix, bytelen); + addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src.u.prefix, bytelen); + + if (index > 0) + addattr32 (&req.n, sizeof req, RTA_OIF, index); + + /* Destination netlink address. */ + memset (&snl, 0, sizeof snl); + snl.nl_family = AF_NETLINK; + + if (! cmd) + zlog_warn ("netlink_routeconnected: connected route for if %s (%s) for net %s src %s in fib", ifc->ifp->name, bufaddr, bufnet, bufsrc); + else + zlog_warn ("netlink_routeconnected: connected route for if %s (%s) for net %s src %s in fib", ifc->ifp->name, bufaddr, bufnet, bufsrc); + + /* Talk to netlink socket. */ + ret = netlink_talk (&req.n, &netlink); + if (ret < 0) + return -1; + + if (! cmd) + zlog_warn ("netlink_routeconnected: ACK: connected route for if %s (%s) for net %s src %s in fib", ifc->ifp->name, bufaddr, bufnet, bufsrc); + else + zlog_warn ("netlink_routeconnected: ACK: connected route for if %s (%s) for net %s src %s in fib", ifc->ifp->name, bufaddr, bufnet, bufsrc); + + return 0; +} + +int +kernel_connected_up (struct connected *ifc) +{ + return netlink_routeconnected (0, ifc); +} + +int +kernel_connected_down (struct connected *ifc) +{ + return netlink_routeconnected (1, ifc); +} + /* Routing table change via netlink interface. */ int netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, diff -Naur quagga-0.98.2/zebra/rt_socket.c quagga-0.98.2-route-connected-fix-ipv6-fix/zebra/rt_socket.c --- quagga-0.98.2/zebra/rt_socket.c 2004-12-07 22:12:56.000000000 +0100 +++ quagga-0.98.2-route-connected-fix-ipv6-fix/zebra/rt_socket.c 2005-02-23 09:59:09.918749264 +0100 @@ -480,4 +480,18 @@ return route; } + +/* Dummy function */ +int +kernel_connected_up (struct connected *ifc) +{ + return 0; +} + +/* Dummy function */ +int +kernel_connected_down (struct connected *ifc) +{ + return 0; +} #endif /* HAVE_IPV6 */