implemented bind support (vhost)
[NeonServV5.git] / src / ClientSocket.c
index 7ddaa3e46be9c620693efe469833e87fdbbce804..abf11a1945e0611006a54125947f0f5b223e9214 100644 (file)
@@ -43,7 +43,7 @@ static void init_sockets() {
     sockets->count = 0;
 }
 
-struct ClientSocket* create_socket(char *host, int port, char *pass, char *nick, char *ident, char *realname) {
+struct ClientSocket* create_socket(char *host, int port, char *bindto, char *pass, char *nick, char *ident, char *realname) {
     if(sockets == NULL) init_sockets();
     struct ClientSocket *client = malloc(sizeof(*client));
     if (!client)
@@ -53,6 +53,7 @@ struct ClientSocket* create_socket(char *host, int port, char *pass, char *nick,
     }
     client->host = strdup(host);
     client->port = port;
+    client->bind = (bindto ? strdup(bindto) : NULL);
     client->pass = (pass == NULL ? NULL : strdup(pass));
     client->nick = strdup(nick);
     client->ident = strdup(ident);
@@ -111,6 +112,23 @@ int connect_socket(struct ClientSocket *client) {
         ip6->sin6_family = AF_INET6;
         ip6->sin6_port = htons(client->port);
         
+        struct sockaddr_in6 *ip6vhost = NULL;
+        if (client->bind && !getaddrinfo(client->bind, NULL, &hints, &res)) {
+            while (res) {
+                switch (res->ai_family) {
+                case AF_INET6:
+                    ip6vhost = (struct sockaddr_in6 *) res->ai_addr;
+                    break;
+                }
+                res = res->ai_next;
+            }
+        }
+        if(ip6vhost) {
+            ip6vhost->sin6_family = AF_INET6;
+            ip6vhost->sin6_port = htons(0);
+            bind(sock, (struct sockaddr*)ip6vhost, sizeof(*ip6vhost));
+        }
+        
         if (connect(sock, (struct sockaddr*)ip6, sizeof(*ip6)) == -1) {
             perror("connect() failed");
             return 0;
@@ -126,6 +144,23 @@ int connect_socket(struct ClientSocket *client) {
         ip4->sin_family = AF_INET;
         ip4->sin_port = htons(client->port);
         
+        struct sockaddr_in *ip4vhost = NULL;
+        if (client->bind && !getaddrinfo(client->bind, NULL, &hints, &res)) {
+            while (res) {
+                switch (res->ai_family) {
+                case AF_INET:
+                    ip4vhost = (struct sockaddr_in *) res->ai_addr;
+                    break;
+                }
+                res = res->ai_next;
+            }
+        }
+        if(ip4vhost) {
+            ip4vhost->sin_family = AF_INET;
+            ip4vhost->sin_port = htons(0);
+            bind(sock, (struct sockaddr*)ip4vhost, sizeof(*ip4vhost));
+        }
+        
         if (connect(sock, (struct sockaddr*)ip4, sizeof(*ip4)) == -1) {
             perror("connect() failed");
             return 0;
@@ -182,7 +217,10 @@ int close_socket(struct ClientSocket *client) {
     if(client->handleinfo_first)
         clear_handleinfoqueue(client);
     free(client->host);
-    free(client->pass);
+    if(client->bind)
+        free(client->bind);
+    if(client->pass)
+        free(client->pass);
     free(client);
     return 1;
 }
@@ -323,7 +361,10 @@ void free_sockets() {
         if(client->queue)
             queue_destroy(client);
         free(client->host);
-        free(client->pass);
+        if(client->bind)
+            free(client->bind);
+        if(client->pass)
+            free(client->pass);
         free(client);
     }
     free(sockets);