components/openvswitch/files/lib/route-table-solaris.c
changeset 5090 5f131162e136
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/openvswitch/files/lib/route-table-solaris.c	Mon Nov 16 16:49:19 2015 -0500
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ */
+
+/*
+ * Copyright (c) 2012 Ed Maste. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <config.h>
+
+#include "route-table.h"
+#include <sys/socket.h>
+#include <sys/types.h>
+
+#include <net/if.h>
+#include <net/route.h>
+#include <net/if_dl.h>
+#include <netinet/in.h>
+
+#include <string.h>
+#include <unistd.h>
+
+#include "util.h"
+
+static int pid;
+static unsigned int register_count = 0;
+
+#define	ROUNDUP_LONG(a) ((a) > 0 ? (1 + (((a) - 1) | (sizeof (long) - 1))) : \
+    sizeof (long))
+#define	RT_ADVANCE(x, n) ((x) += ROUNDUP_LONG(salen(n)))
+#define	BUF_SIZE 2048
+
+typedef struct rtmsg {
+	struct rt_msghdr	m_rtm;
+	char			m_space[BUF_SIZE];
+} rtmsg_t;
+
+static int
+salen(const struct sockaddr *sa)
+{
+	switch (sa->sa_family) {
+	case AF_INET:
+		return (sizeof (struct sockaddr_in));
+	case AF_LINK:
+		return (sizeof (struct sockaddr_dl));
+	case AF_INET6:
+		return (sizeof (struct sockaddr_in6));
+	default:
+		return (sizeof (struct sockaddr));
+	}
+}
+
+bool
+route_table_get_name(ovs_be32 ip, char name[IFNAMSIZ])
+{
+	rtmsg_t			m_rtmsg;
+	struct rt_msghdr	*rtm = &m_rtmsg.m_rtm;
+	char			*cp = m_rtmsg.m_space;
+	int			rtsock_fd;
+	struct sockaddr_in	sin;
+	struct sockaddr_dl	sdl;
+	ssize_t			ssz;
+	static int		seq;
+	int			rlen;
+	int			i;
+	int			l;
+
+	rtsock_fd = socket(PF_ROUTE, SOCK_RAW, 0);
+	if (rtsock_fd == -1)
+		return (false);
+
+	memset(&sin, 0, sizeof (sin));
+	sin.sin_family = AF_INET;
+	sin.sin_port = 0;
+	sin.sin_addr.s_addr = ip;
+
+	memset(&sdl, 0, sizeof (sdl));
+	sdl.sdl_family = AF_LINK;
+
+	memset(&m_rtmsg, 0, sizeof (m_rtmsg));
+	rtm->rtm_version = RTM_VERSION;
+	rtm->rtm_type = RTM_GET;
+	rtm->rtm_addrs = RTA_DST|RTA_IFP;
+	rtm->rtm_seq = ++seq;
+
+	l = ROUNDUP_LONG(sizeof (struct sockaddr_in));
+	(void) memcpy(cp, &sin, l);
+	cp += l;
+
+	l = ROUNDUP_LONG(sizeof (struct sockaddr_dl));
+	(void) memcpy(cp, &sdl, l);
+	cp += l;
+
+	rtm->rtm_msglen = l = cp - (char *)&m_rtmsg;
+	if ((rlen = write(rtsock_fd, (char *)&m_rtmsg, l)) < l) {
+		close(rtsock_fd);
+		return (false);
+	}
+
+	do {
+		ssz = read(rtsock_fd, &m_rtmsg, sizeof (m_rtmsg));
+	} while (ssz > 0 && (rtm->rtm_seq != seq || rtm->rtm_pid != pid));
+	close(rtsock_fd);
+
+	if (ssz < 0)
+		return (false);
+
+	cp = (void *)&m_rtmsg.m_space;
+	for (i = 1; i; i <<= 1) {
+		if ((rtm->rtm_addrs & i) != 0) {
+			const struct sockaddr *sa = (const void *)cp;
+
+			if ((i == RTA_IFP) && sa->sa_family == AF_LINK) {
+				const struct sockaddr_dl * const sdlp =
+				    ALIGNED_CAST(const struct sockaddr_dl *,
+				    sa);
+				int namelen;
+
+				namelen = sdlp->sdl_nlen;
+				if (namelen > IFNAMSIZ - 1)
+					namelen = IFNAMSIZ - 1;
+				memcpy(name, sdlp->sdl_data, namelen);
+				name[namelen] = '\0';
+				return (true);
+			}
+			RT_ADVANCE(cp, sa);
+		}
+	}
+	return (false);
+}
+
+uint64_t
+route_table_get_change_seq(void)
+{
+	return (0);
+}
+
+void
+route_table_register(void)
+{
+	if (!register_count) {
+		pid = getpid();
+	}
+
+	register_count++;
+}
+
+void
+route_table_unregister(void)
+{
+	register_count--;
+}
+
+void
+route_table_run(void)
+{
+}
+
+void
+route_table_wait(void)
+{
+}