nixio: More sockopts
[project/luci.git] / libs / nixio / src / sockopt.c
index 68a4c55..2d68d12 100644 (file)
  */
 
 #include "nixio.h"
+#include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <netinet/tcp.h>
+#include <net/if.h>
 #include <sys/time.h>
 #include <string.h>
 #include <fcntl.h>
+#include <errno.h>
 #include "nixio.h"
 
+
 /**
  * setblocking()
  */
@@ -104,6 +108,30 @@ static int nixio__gso_timev(lua_State *L, int fd, int level, int opt, int set) {
        return nixio__perror(L);
 }
 
+#ifdef SO_BINDTODEVICE
+
+static int nixio__gso_b(lua_State *L, int fd, int level, int opt, int set) {
+       if (!set) {
+               socklen_t optlen = IFNAMSIZ;
+               char ifname[IFNAMSIZ];
+               if (!getsockopt(fd, level, opt, ifname, &optlen)) {
+                       lua_pushlstring(L, ifname, optlen);
+                       return 1;
+               }
+       } else {
+               size_t valuelen;
+               const char *value = luaL_checklstring(L, set, &valuelen);
+               luaL_argcheck(L, valuelen <= IFNAMSIZ, set, "invalid interface name");
+               if (!setsockopt(fd, level, opt, value, valuelen)) {
+                       lua_pushboolean(L, 1);
+                       return 1;
+               }
+       }
+       return nixio__perror(L);
+}
+
+#endif /* SO_BINDTODEVICE */
+
 /**
  * get/setsockopt() helper
  */
@@ -123,18 +151,35 @@ static int nixio__getsetsockopt(lua_State *L, int set) {
                } else if (!strcmp(option, "sndbuf")) {
                        return nixio__gso_int(L, sock->fd, SOL_SOCKET, SO_SNDBUF, set);
                } else if (!strcmp(option, "priority")) {
+#ifdef SO_PRIORITY
                        return nixio__gso_int(L, sock->fd, SOL_SOCKET, SO_PRIORITY, set);
+#else
+                       return nixio__pstatus(L, !(errno = ENOPROTOOPT));
+#endif
                } else if (!strcmp(option, "broadcast")) {
                        return nixio__gso_int(L, sock->fd, SOL_SOCKET, SO_BROADCAST, set);
+               } else if (!strcmp(option, "dontroute")) {
+                       return nixio__gso_int(L, sock->fd, SOL_SOCKET, SO_DONTROUTE, set);
+               } else if (!strcmp(option, "error")) {
+                       return nixio__gso_int(L, sock->fd, SOL_SOCKET, SO_ERROR, set);
+               } else if (!strcmp(option, "oobinline")) {
+                       return nixio__gso_int(L, sock->fd, SOL_SOCKET, SO_OOBINLINE, set);
                } else if (!strcmp(option, "linger")) {
                        return nixio__gso_ling(L, sock->fd, SOL_SOCKET, SO_LINGER, set);
                } else if (!strcmp(option, "sndtimeo")) {
                        return nixio__gso_timev(L, sock->fd, SOL_SOCKET, SO_SNDTIMEO, set);
                } else if (!strcmp(option, "rcvtimeo")) {
                        return nixio__gso_timev(L, sock->fd, SOL_SOCKET, SO_RCVTIMEO, set);
+               } else if (!strcmp(option, "bindtodevice")) {
+#ifdef SO_BINDTODEVICE
+                       return nixio__gso_b(L, sock->fd, SOL_SOCKET, SO_BINDTODEVICE, set);
+#else
+                       return nixio__pstatus(L, !(errno = ENOPROTOOPT));
+#endif
                } else {
                        return luaL_argerror(L, 3, "supported values: keepalive, reuseaddr,"
-                        " sndbuf, rcvbuf, priority, broadcast, linger, sndtimeo, rcvtimeo"
+                        " sndbuf, rcvbuf, priority, broadcast, linger, sndtimeo, rcvtimeo,"
+                        " dontroute, bindtodevice, error, oobinline"
                        );
                }
        } else if (!strcmp(level, "tcp")) {
@@ -142,9 +187,13 @@ static int nixio__getsetsockopt(lua_State *L, int set) {
                        return luaL_error(L, "not a TCP socket");
                }
                if (!strcmp(option, "cork")) {
-                       return nixio__gso_int(L, sock->fd, SOL_TCP, TCP_CORK, set);
+#ifdef TCP_CORK
+                       return nixio__gso_int(L, sock->fd, IPPROTO_TCP, TCP_CORK, set);
+#else
+                       return nixio__pstatus(L, !(errno = ENOPROTOOPT));
+#endif
                } else if (!strcmp(option, "nodelay")) {
-                       return nixio__gso_int(L, sock->fd, SOL_TCP, TCP_NODELAY, set);
+                       return nixio__gso_int(L, sock->fd, IPPROTO_TCP, TCP_NODELAY, set);
                } else {
                        return luaL_argerror(L, 3, "supported values: cork, nodelay");
                }