diff options
Diffstat (limited to 'zebra')
-rw-r--r-- | zebra/interface.c | 59 | ||||
-rw-r--r-- | zebra/interface.h | 14 | ||||
-rw-r--r-- | zebra/kernel_socket.c | 12 | ||||
-rw-r--r-- | zebra/rtadv.c | 137 | ||||
-rw-r--r-- | zebra/rtadv.h | 12 |
5 files changed, 234 insertions, 0 deletions
diff --git a/zebra/interface.c b/zebra/interface.c index e09ca41f..e19648d7 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -83,6 +83,10 @@ if_zebra_new_hook (struct interface *ifp) rtadv->DefaultPreference = RTADV_PREF_MEDIUM; rtadv->AdvPrefixList = list_new (); + + rtadv->AdvRDNSSFlag = 0; + rtadv->AdvRDNSSLifetime = RTADV_RDNSS_DEFAULT_LIFETIME; + rtadv->AdvRDNSSList = list_new (); } #endif /* RTADV */ @@ -655,6 +659,9 @@ nd_dump_vty (struct vty *vty, struct interface *ifp) vty_out (vty, " ND router advertisements with " "Home Agent flag bit set.%s", VTY_NEWLINE); + if (rtadv->AdvRDNSSFlag) + vty_out (vty, " ND router advertisements with " + "RDNSS information.%s", VTY_NEWLINE); if (rtadv->AdvIntervalOption) vty_out (vty, " ND router advertisements with Adv. Interval option.%s", VTY_NEWLINE); @@ -1016,6 +1023,53 @@ DEFUN (no_multicast, return CMD_SUCCESS; } +DEFUN (unnumbered, + unnumbered_cmd, + "unnumbered", + "Set interface to IP Unnumbered mode\n") +{ + int ret; + struct interface *ifp; + struct zebra_if *if_data; + + ifp = (struct interface *) vty->index; + + zlog_debug("VTY: interface %s, Setting ifp->status |= ZEBRA_INTERFACE_UNNUMBERED", + ifp->name); + + SET_FLAG(ifp->status, ZEBRA_INTERFACE_UNNUMBERED); + + /* force protocols to recalculate routes due to IP change */ + if (if_is_operative (ifp)) + zebra_interface_up_update (ifp); + + return CMD_SUCCESS; +} + +DEFUN (no_unnumbered, + no_unnumbered_cmd, + "no unnumbered", + NO_STR + "Set interface to IP Numbered mode\n") +{ + int ret; + struct interface *ifp; + struct zebra_if *if_data; + + ifp = (struct interface *) vty->index; + + zlog_debug("VTY: interface %s, Setting ifp->status &= ~ZEBRA_INTERFACE_UNNUMBERED;", + ifp->name); + + UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_UNNUMBERED); + + /* force protocols to recalculate routes due to IP change */ + if (if_is_operative (ifp)) + zebra_interface_up_update (ifp); + + return CMD_SUCCESS; +} + DEFUN (linkdetect, linkdetect_cmd, "link-detect", @@ -1711,6 +1765,9 @@ if_config_write (struct vty *vty) if (ifp->bandwidth != 0) vty_out(vty, " bandwidth %u%s", ifp->bandwidth, VTY_NEWLINE); + if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_UNNUMBERED)) + vty_out (vty, " unnumbered%s", VTY_NEWLINE); + if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)) vty_out(vty, " link-detect%s", VTY_NEWLINE); @@ -1791,6 +1848,8 @@ zebra_if_init (void) install_element (INTERFACE_NODE, &no_interface_desc_cmd); install_element (INTERFACE_NODE, &multicast_cmd); install_element (INTERFACE_NODE, &no_multicast_cmd); + install_element (INTERFACE_NODE, &unnumbered_cmd); + install_element (INTERFACE_NODE, &no_unnumbered_cmd); install_element (INTERFACE_NODE, &linkdetect_cmd); install_element (INTERFACE_NODE, &no_linkdetect_cmd); install_element (INTERFACE_NODE, &shutdown_if_cmd); diff --git a/zebra/interface.h b/zebra/interface.h index 0cf66403..305abaac 100644 --- a/zebra/interface.h +++ b/zebra/interface.h @@ -178,6 +178,20 @@ struct rtadvconf Default: 0 (medium) */ int DefaultPreference; #define RTADV_PREF_MEDIUM 0x0 /* Per RFC4191. */ + + /* A list of Recursive DNS server addresses specified in + RFC 5006 */ + int AdvRDNSSFlag; + struct list *AdvRDNSSList; + + /* the maximum lifetime in seconds over which the RDNSS entry + * may be used. After this time a host may send a router solicitation + * message to refresh the RDNSS information. + * + * Default is infinity lifetime (0xffffffff) */ + uint32_t AdvRDNSSLifetime; +#define RTADV_RDNSS_INFINITY_LIFETIME (0xffffffff) +#define RTADV_RDNSS_DEFAULT_LIFETIME RTADV_RDNSS_INFINITY_LIFETIME }; #endif /* RTADV */ diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index aa962a35..639617a5 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -338,6 +338,7 @@ int ifm_read (struct if_msghdr *ifm) { struct interface *ifp = NULL; + struct sockaddr_dl *sdl; char ifname[IFNAMSIZ]; short ifnlen = 0; caddr_t *cp; @@ -375,6 +376,7 @@ ifm_read (struct if_msghdr *ifm) RTA_ADDR_GET (NULL, RTA_GATEWAY, ifm->ifm_addrs, cp); RTA_ATTR_GET (NULL, RTA_NETMASK, ifm->ifm_addrs, cp); RTA_ADDR_GET (NULL, RTA_GENMASK, ifm->ifm_addrs, cp); + sdl = (struct sockaddr_dl *)cp; RTA_NAME_GET (ifname, RTA_IFP, ifm->ifm_addrs, cp, ifnlen); RTA_ADDR_GET (NULL, RTA_IFA, ifm->ifm_addrs, cp); RTA_ADDR_GET (NULL, RTA_AUTHOR, ifm->ifm_addrs, cp); @@ -473,6 +475,16 @@ ifm_read (struct if_msghdr *ifm) #endif /* __bsdi__ */ if_get_metric (ifp); + /* + * XXX sockaddr_dl contents can be larger than the structure + * definition, so the user of the stored structure must be + * careful not to read off the end. + * + * a nonzero ifnlen from RTA_NAME_GET() means sdl is valid + */ + if (ifnlen) + memcpy (&ifp->sdl, sdl, sizeof (struct sockaddr_dl)); + if_add_update (ifp); } else diff --git a/zebra/rtadv.c b/zebra/rtadv.c index 8cc3c4cb..7d9c0f6c 100644 --- a/zebra/rtadv.c +++ b/zebra/rtadv.c @@ -233,6 +233,32 @@ rtadv_send_packet (int sock, struct interface *ifp) len += sizeof(struct nd_opt_homeagent_info); } + if (zif->rtadv.AdvRDNSSFlag) + { + char *addr_ptr; + struct nd_opt_rdnss *ndopt_rdnss; + struct prefix *rdnss_prefix; + unsigned int rdnss_entries = 1; + + ndopt_rdnss = (struct nd_opt_rdnss *) (buf + len); + ndopt_rdnss->nd_opt_type = ND_OPT_RDNSS; + ndopt_rdnss->nd_opt_reserved = 0; + ndopt_rdnss->nd_opt_lifetime = htonl(zif->rtadv.AdvRDNSSLifetime); + + len += sizeof(struct nd_opt_rdnss); + + /* Fill in all RDNS server entries */ + for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvRDNSSList, node, rdnss_prefix)) + { + addr_ptr = (char *)(buf + len); + memcpy(addr_ptr, &rdnss_prefix->u.prefix6, sizeof (struct in6_addr)); + len += sizeof (struct in6_addr); + rdnss_entries += 2; + } + + ndopt_rdnss->nd_opt_len = rdnss_entries; + } + if (zif->rtadv.AdvIntervalOption) { struct nd_opt_adv_interval *ndopt_adv = @@ -1430,6 +1456,115 @@ DEFUN (no_ipv6_nd_router_preference, return CMD_SUCCESS; } +static struct prefix * +rtadv_rdnss_lookup (struct list *list, struct prefix *p) +{ + struct listnode *node; + struct prefix *prefix; + + for (ALL_LIST_ELEMENTS_RO (list, node, prefix)) + if (prefix_same (prefix, p)) + return prefix; + return NULL; +} + +static void +rtadv_rdnss_set (struct zebra_if *zif, struct prefix *p) +{ + struct prefix *prefix; + struct list *rdnsslist = zif->rtadv.AdvRDNSSList; + + prefix = rtadv_rdnss_lookup (rdnsslist, p); + if (prefix) + return; + + prefix = prefix_new (); + memcpy (prefix, p, sizeof (struct prefix)); + listnode_add (rdnsslist, prefix); + + return; +} + +static int +rtadv_rdnss_reset (struct zebra_if *zif, struct prefix *rp) +{ + struct prefix *prefix; + + prefix = rtadv_rdnss_lookup(zif->rtadv.AdvRDNSSList, rp); + if (prefix != NULL) + { + listnode_delete (zif->rtadv.AdvRDNSSList, (void *) prefix); + prefix_free (prefix); + return 1; + } + else + return 0; +} + +DEFUN (ipv6_nd_rdnss, + ipv6_nd_rdnss_cmd, + "ipv6 nd rdnss X:X::X:X (<0-4294967295>|infinite)", + "Interface IPv6 config commands\n" + "Neighbor discovery\n" + "RDNSS Option\n" + "IPv6 address of recursive DNS server\n") +{ + int ret; + char *pnt; + struct interface *ifp; + struct zebra_if *zif; + struct prefix rp; + + ifp = (struct interface *) vty->index; + zif = ifp->info; + + /* make sure no slash exists in the argument */ + pnt = strchr (argv[0], '/'); + if (pnt != NULL) + { + vty_out (vty, "Malformed IPv6 RDNS address - no prefix notation allowed%s", + VTY_NEWLINE); + return CMD_WARNING; + } + + /* now we can abuse str2prefix_ipv6 for a sanity check + * because IPv6 addresses with missing prefix + * slashes '/' are treated as host routes */ + ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &rp); + if (!ret) + { + vty_out (vty, "Malformed IPv6 RDNS address%s", VTY_NEWLINE); + return CMD_WARNING; + } + + rtadv_rdnss_set(zif, &rp); + zif->rtadv.AdvRDNSSFlag = 1; + + if (argc > 1) + { + if ( strncmp (argv[1], "i", 1) == 0) + { + zif->rtadv.AdvRDNSSLifetime = RTADV_RDNSS_INFINITY_LIFETIME; + } + else + { + zif->rtadv.AdvRDNSSLifetime = + (u_int32_t) strtoll (argv[1], (char **)NULL, 10); + } + } + + return CMD_SUCCESS; +} + +ALIAS (ipv6_nd_rdnss, + ipv6_nd_rdnss_nolife_cmd, + "ipv6 nd rdnss X:X::X:X", + "Interface IPv6 config commands\n" + "Neighbor discovery\n" + "RDNSS Option\n" + "IPv6 address of recursive DNS server\n") + + /* Write configuration about router advertisement. */ void rtadv_config_write (struct vty *vty, struct interface *ifp) @@ -1605,6 +1740,8 @@ rtadv_init (void) install_element (INTERFACE_NODE, &no_ipv6_nd_prefix_cmd); install_element (INTERFACE_NODE, &ipv6_nd_router_preference_cmd); install_element (INTERFACE_NODE, &no_ipv6_nd_router_preference_cmd); + install_element (INTERFACE_NODE, &ipv6_nd_rdnss_cmd); + install_element (INTERFACE_NODE, &ipv6_nd_rdnss_nolife_cmd); } static int diff --git a/zebra/rtadv.h b/zebra/rtadv.h index d8d263d0..0893ba53 100644 --- a/zebra/rtadv.h +++ b/zebra/rtadv.h @@ -66,6 +66,9 @@ extern void rtadv_init (void); #ifndef ND_OPT_HA_INFORMATION #define ND_OPT_HA_INFORMATION 8 /* HA Information Option */ #endif +#ifndef ND_OPT_RDNSS +#define ND_OPT_RDNSS 25 /* RDNSS option (RFC 5006) */ +#endif #ifndef HAVE_STRUCT_ND_OPT_ADV_INTERVAL struct nd_opt_adv_interval { /* Advertisement interval option */ @@ -94,6 +97,15 @@ struct nd_opt_homeagent_info { /* Home Agent info */ } __attribute__((__packed__)); #endif +/* see RFC 5006, section 5.1 */ +struct nd_opt_rdnss { + uint8_t nd_opt_type; + uint8_t nd_opt_len; + uint16_t nd_opt_reserved; + uint32_t nd_opt_lifetime; + /* followed by n (16 byte) entries */ +} __attribute__((__packed__)); + extern const char *rtadv_pref_strs[]; #endif /* _ZEBRA_RTADV_H */ |