add function to bind a udp rpc context to a local port/address
authorRonnie Sahlberg <ronniesahlberg@gmail.com>
Sun, 26 Jun 2011 08:40:00 +0000 (18:40 +1000)
committerRonnie Sahlberg <ronniesahlberg@gmail.com>
Sun, 26 Jun 2011 08:40:00 +0000 (18:40 +1000)
include/libnfs-private.h
lib/socket.c

index 2671a2bee138e1e1ee2d58980ce864782259ffb7..883745b5c7b11e60e9d360d2b57a39373ca205d1 100644 (file)
@@ -76,4 +76,6 @@ void nfs_set_error(struct nfs_context *nfs, char *error_string, ...);
 
 struct rpc_context *nfs_get_rpc_context(struct nfs_context *nfs);
 
+/* we dont want to expose UDP to normal applications/users  this is private to libnfs to use exclusively for broadcast RPC */
+int rpc_bind_udp(struct rpc_context *rpc, char *addr, int port);
 struct rpc_context *rpc_init_udp_context(void);
index a0ededa61a625f7cc463b1a2d4da8cca78dcf1de..3e4ad05062011041ecb002bd24589850a2ed244c 100644 (file)
@@ -26,6 +26,9 @@
 #include <rpc/xdr.h>
 #include <arpa/inet.h>
 #include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
 #include "libnfs.h"
 #include "libnfs-raw.h"
 #include "libnfs-private.h"
@@ -340,3 +343,48 @@ int rpc_disconnect(struct rpc_context *rpc, char *error)
 
        return 0;
 }
+
+
+int rpc_bind_udp(struct rpc_context *rpc, char *addr, int port)
+{
+       struct addrinfo *ai = NULL;
+       char service[6];
+
+       if (rpc->is_udp == 0) {
+               rpc_set_error(rpc, "Cant not bind UDP. Not UDP context");
+               return -1;
+       }
+
+       snprintf(service, 6, "%d", port);
+       if (getaddrinfo(addr, service, NULL, &ai) != 0) {
+               rpc_set_error(rpc, "Invalid address:%s. "
+                       "Can not resolv into IPv4/v6 structure.");
+               return -1;
+       }
+
+       switch(ai->ai_family) {
+       case AF_INET:
+               rpc->fd = socket(ai->ai_family, SOCK_DGRAM, 0);
+               if (rpc->fd == -1) {
+                       rpc_set_error(rpc, "Failed to create UDP socket: %s", strerror(errno)); 
+                       freeaddrinfo(ai);
+                       return -1;
+               }
+
+               if (bind(rpc->fd, (struct sockaddr *)ai->ai_addr, sizeof(struct sockaddr_in)) != 0) {
+                       rpc_set_error(rpc, "Failed to bind to UDP socket: %s",strerror(errno)); 
+                       freeaddrinfo(ai);
+                       return -1;
+               }
+               break;
+       default:
+               rpc_set_error(rpc, "Can not handle UPD sockets of family %d yet", ai->ai_family);
+               freeaddrinfo(ai);
+               return -1;
+       }
+
+       freeaddrinfo(ai);
+
+       return 0;
+}
+