summaryrefslogtreecommitdiff
path: root/zebra/ipforward_solaris.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/ipforward_solaris.c')
-rw-r--r--zebra/ipforward_solaris.c130
1 files changed, 95 insertions, 35 deletions
diff --git a/zebra/ipforward_solaris.c b/zebra/ipforward_solaris.c
index 99b0e1a8..63d1110c 100644
--- a/zebra/ipforward_solaris.c
+++ b/zebra/ipforward_solaris.c
@@ -21,57 +21,117 @@
*/
#include <zebra.h>
+#include "log.h"
-#include "memory.h"
+/*
+** Solaris should define IP_DEV_NAME in <inet/ip.h>, but we'll save
+** configure.in changes for another day. We can use the same device
+** for both IPv4 and IPv6.
+*/
+/* #include <inet/ip.h> */
+#ifndef IP_DEV_NAME
+#define IP_DEV_NAME "/dev/ip"
+#endif
+/*
+** This is a limited ndd style function that operates one integer
+** value only. Errors return -1. ND_SET commands return 0 on
+** success. ND_GET commands return the value on success (which could
+** be -1 and be confused for an error). The parameter is the string
+** name of the parameter being referenced.
+*/
-int
-ipforward ()
+static int
+solaris_nd(const int cmd, const char* parameter, const int value)
{
- int fd, ret;
- int ipforwarding = 0;
- char forward[] = "ip_forwarding";
- char *buf;
- struct strioctl si;
-
- buf = (char *) XMALLOC (MTYPE_TMP, sizeof forward + 1);
- strcpy (buf, forward);
-
- fd = open ("/dev/ip", O_RDWR);
- if (fd < 0) {
- free (buf);
- /* need logging here */
- /* "I can't get ipforwarding value because can't open /dev/ip" */
+#define ND_BUFFER_SIZE 1024
+ int fd;
+ char nd_buf[ND_BUFFER_SIZE];
+ struct strioctl strioctl;
+ const char* device = IP_DEV_NAME;
+ int retval;
+ memset(nd_buf, '\0', ND_BUFFER_SIZE);
+ /*
+ ** ND_SET takes a NULL delimited list of strings further terminated
+ ** buy a NULL. ND_GET returns a list in a similar layout, although
+ ** here we only use the first result.
+ */
+ if (cmd == ND_SET) {
+ snprintf(nd_buf, ND_BUFFER_SIZE, "%s%c%d%c", parameter, '\0', value,'\0');
+ } else if (cmd == ND_GET) {
+ snprintf(nd_buf, ND_BUFFER_SIZE, "%s", parameter);
+ } else {
+ zlog_err("internal error - inappropriate command given to solaris_nd()%s:%d", __FILE__, __LINE__);
return -1;
}
-
- si.ic_cmd = ND_GET;
- si.ic_timout = 0;
- si.ic_len = strlen (buf) + 1;
- si.ic_dp = (caddr_t) buf;
-
- ret = ioctl (fd, I_STR, &si);
- close (fd);
-
- if (ret < 0) {
- free (buf);
- /* need logging here */
- /* can't get ipforwarding value : ioctl failed */
+ strioctl.ic_cmd = cmd;
+ strioctl.ic_timout = 0;
+ strioctl.ic_len = ND_BUFFER_SIZE;
+ strioctl.ic_dp = nd_buf;
+ if ((fd = open (device, O_RDWR)) < 0) {
+ zlog_warn("failed to open device %s - %s", device, strerror(errno));
+ return -1;
+ }
+ if (ioctl (fd, I_STR, &strioctl) < 0) {
+ close (fd);
+ zlog_warn("ioctl I_STR failed on device %s - %s", device,strerror(errno));
return -1;
}
+ close(fd);
+ if (cmd == ND_GET) {
+ errno = 0;
+ retval = atoi(nd_buf);
+ if (errno) {
+ zlog_warn("failed to convert returned value to integer - %s",strerror(errno));
+ retval = -1;
+ }
+ } else {
+ retval = 0;
+ }
+ return retval;
+}
- ipforwarding = atoi (buf);
- free (buf);
- return ipforwarding;
+static int
+solaris_nd_set(const char* parameter, const int value) {
+ return solaris_nd(ND_SET, parameter, value);
+}
+static int
+solaris_nd_get(const char* parameter) {
+ return solaris_nd(ND_GET, parameter, 0);
+}
+int
+ipforward()
+{
+ return solaris_nd_get("ip_forwarding");
}
int
ipforward_on ()
{
- return 0;
+ (void) solaris_nd_set("ip_forwarding", 1);
+ return ipforward();
}
int
ipforward_off ()
{
- return 0;
+ (void) solaris_nd_set("ip_forwarding", 0);
+ return ipforward();
+}
+#ifdef HAVE_IPV6
+int ipforward_ipv6()
+{
+ return solaris_nd_get("ip6_fowarding");
+}
+int
+ipforward_ipv6_on ()
+{
+ (void) solaris_nd_set("ip6_forwarding", 1);
+ return ipforward_ipv6();
+}
+int
+ipforward_ipv6_off ()
+{
+ (void) solaris_nd_set("ip6_forwarding", 0);
+ return ipforward_ipv6();
}
+#endif /* HAVE_IPV6 */