summaryrefslogtreecommitdiffstats
path: root/zebra/if_ioctl_solaris.c
diff options
context:
space:
mode:
authorpaul <paul>2005-11-03 12:35:21 +0000
committerpaul <paul>2005-11-03 12:35:21 +0000
commit1cded5becce446c14f1ae51151ea3e3284876a9d (patch)
tree387e7bdd265bdb617dfacb4adc98ce5064584b42 /zebra/if_ioctl_solaris.c
parent097f8dae4b9e6e5b258ec13afe604a3aab5618f1 (diff)
downloadquagga-1cded5becce446c14f1ae51151ea3e3284876a9d.tar.bz2
quagga-1cded5becce446c14f1ae51151ea3e3284876a9d.tar.xz
2005-11-03 Paul Jakma <paul.jakma@sun.com>
* connected.{c,h}: Include memory.h (connected_add_ipv4) Use MTYPE for ifc label. (connected_add_ipv6) Also should accept label. Store it in ifp. (connected_del_ipv4) Taking label as argument is pointless. * rt_netlink.c: (netlink_interface_addr) update label usage for connected_{add,delete} functions. * if_ioctl.c: (if_getaddrs) NULL label for connected_add_ipv6. * if_ioctl_solaris.c: (interface_list_ioctl) Pass LIFC_NOXMIT so we also find out about NOXMIT interfaces like VNI. Bit of hackery to turn interface names into the primary interface name, later with routing socket messages we only will about primary interfaces anyway, so we must normalise the name. (if_get_addr) take label as argument, so it can be passed to connected_add. If label is provided, then it is interface name to issue the ioctl for address information on, not the ifp name. (interface_list) List AF_UNSPEC too, just in case. * if_proc.c: (ifaddr_proc_ipv6) label for connected_add_ipv6. * interface.c: (if_addr_wakeup) Some very bogus code - sets IFF_RUNNING - add comment. (if_refresh) (ip_address_install) Use MTYPE for ifc label. * ioctl_solaris.c: (if_mangle_up) New function. Hackery to make IFF_UP reflect whether any addresses are left on the interface, as we get signalled for IFF_UP flags change on the primary interface only. Logical interfaces dont generate IFINFO, but we do get an RTM_DELADDR. (if_get_flags) Call if_mangle_up before return. * kernel_socket.c: (ifam_read) Fixup calls to connected_{add,delete} to match above changes. Rename gate variable to brd, less confusing. Pass the interface name as a label, if it is not same name as ifp->name.
Diffstat (limited to 'zebra/if_ioctl_solaris.c')
-rw-r--r--zebra/if_ioctl_solaris.c50
1 files changed, 38 insertions, 12 deletions
diff --git a/zebra/if_ioctl_solaris.c b/zebra/if_ioctl_solaris.c
index efa65060..898c1610 100644
--- a/zebra/if_ioctl_solaris.c
+++ b/zebra/if_ioctl_solaris.c
@@ -34,7 +34,7 @@
#include "zebra/interface.h"
void lifreq_set_name (struct lifreq *, struct interface *);
-static int if_get_addr (struct interface *, struct sockaddr *);
+static int if_get_addr (struct interface *, struct sockaddr *, const char *);
static void interface_info_ioctl (struct interface *);
extern struct zebra_privs_t zserv_privs;
@@ -71,7 +71,7 @@ interface_list_ioctl (int af)
calculate_lifc_len: /* must hold privileges to enter here */
lifn.lifn_family = af;
- lifn.lifn_flags = 0;
+ lifn.lifn_flags = LIFC_NOXMIT; /* we want NOXMIT interfaces too */
ret = ioctl (sock, SIOCGLIFNUM, &lifn);
save_errno = errno;
@@ -108,7 +108,7 @@ calculate_lifc_len: /* must hold privileges to enter here */
lastneeded = needed;
lifconf.lifc_family = af;
- lifconf.lifc_flags = 0;
+ lifconf.lifc_flags = LIFC_NOXMIT;
lifconf.lifc_len = needed;
lifconf.lifc_buf = buf;
@@ -138,9 +138,22 @@ calculate_lifc_len: /* must hold privileges to enter here */
for (n = 0; n < lifconf.lifc_len; n += sizeof (struct lifreq))
{
- ifp = if_get_by_name_len(lifreq->lifr_name,
- strnlen(lifreq->lifr_name,
- sizeof(lifreq->lifr_name)));
+ /* we treat Solaris logical interfaces as addresses, because that is
+ * how PF_ROUTE on Solaris treats them. Hence we can not directly use
+ * the lifreq_name to get the ifp. We need to normalise the name
+ * before attempting get.
+ *
+ * Solaris logical interface names are in the form of:
+ * <interface name>:<logical interface id>
+ */
+ unsigned int normallen = 0;
+
+ while ( (normallen < sizeof(lifreq->lifr_name))
+ && ( *(lifreq->lifr_name + normallen) != '\0')
+ && ( *(lifreq->lifr_name + normallen) != ':') )
+ normallen++;
+
+ ifp = if_get_by_name_len(lifreq->lifr_name, normallen);
if (lifreq->lifr_addr.ss_family == AF_INET)
ifp->flags |= IFF_IPV4;
@@ -158,7 +171,15 @@ calculate_lifc_len: /* must hold privileges to enter here */
if_add_update (ifp);
interface_info_ioctl (ifp);
- if_get_addr (ifp, (struct sockaddr *) &lifreq->lifr_addr);
+
+ /* If a logical interface pass the full name so it can be
+ * as a label on the address
+ */
+ if ( *(lifreq->lifr_name + normallen) != '\0')
+ if_get_addr (ifp, (struct sockaddr *) &lifreq->lifr_addr,
+ lifreq->lifr_name);
+ else
+ if_get_addr (ifp, (struct sockaddr *) &lifreq->lifr_addr, NULL);
lifreq++;
}
@@ -209,8 +230,9 @@ if_get_index (struct interface *ifp)
#define SIN(s) ((struct sockaddr_in *)(s))
#define SIN6(s) ((struct sockaddr_in6 *)(s))
+/* Retrieve address information for the given ifp */
static int
-if_get_addr (struct interface *ifp, struct sockaddr *addr)
+if_get_addr (struct interface *ifp, struct sockaddr *addr, const char *label)
{
int ret;
struct lifreq lifreq;
@@ -219,8 +241,11 @@ if_get_addr (struct interface *ifp, struct sockaddr *addr)
u_char prefixlen = 0;
afi_t af;
- /* Interface's name and address family. */
- strncpy (lifreq.lifr_name, ifp->name, IFNAMSIZ);
+ /* Interface's name and address family.
+ * We need to use the logical interface name / label, if we've been
+ * given one, in order to get the right address
+ */
+ strncpy (lifreq.lifr_name, (label : label ? ifp->name), IFNAMSIZ);
/* Interface's address. */
memcpy (&lifreq.lifr_addr, addr, ADDRLEN (addr));
@@ -306,11 +331,11 @@ if_get_addr (struct interface *ifp, struct sockaddr *addr)
/* Set address to the interface. */
if (af == AF_INET)
connected_add_ipv4 (ifp, 0, &SIN (addr)->sin_addr, prefixlen,
- (struct in_addr *) dest_pnt, NULL);
+ (struct in_addr *) dest_pnt, label);
#ifdef HAVE_IPV6
else if (af == AF_INET6)
connected_add_ipv6 (ifp, &SIN6 (addr)->sin6_addr, prefixlen,
- (struct in6_addr *) dest_pnt);
+ (struct in6_addr *) dest_pnt, label);
#endif /* HAVE_IPV6 */
return 0;
@@ -332,6 +357,7 @@ interface_list ()
{
interface_list_ioctl (AF_INET);
interface_list_ioctl (AF_INET6);
+ interface_list_ioctl (AF_UNSPEC);
}
struct connected *