Example code: Don't create rs_error on failing context creation.
[radsecproxy.git] / hostport.c
index 9360299..54c1d74 100644 (file)
@@ -6,9 +6,16 @@
  * copyright notice and this permission notice appear in all copies.
  */
 
+/* Code contributions from:
+ *
+ * Simon Leinen <simon.leinen@switch.ch>
+ */
+
 #include <stdlib.h>
+#include <unistd.h>
 #include <string.h>
 #include <netdb.h>
+#include <netinet/in.h>
 #include "debug.h"
 #include "util.h"
 #include "list.h"
@@ -61,24 +68,24 @@ static int parsehostport(struct hostportres *hp, char *hostport, char *default_p
        }
     }
     if (*p == ':') {
-           /* port number or service name is specified */;
-           field = ++p;
-           for (; *p && *p != ' ' && *p != '\t' && *p != '\n'; p++);
-           if (field == p) {
-               debug(DBG_ERR, "syntax error, : but no following port");
-               return 0;
-           }
-           hp->port = stringcopy(field, p - field);
+       /* port number or service name is specified */;
+       field = ++p;
+       for (; *p && *p != ' ' && *p != '\t' && *p != '\n'; p++);
+       if (field == p) {
+           debug(DBG_ERR, "syntax error, : but no following port");
+           return 0;
+       }
+       hp->port = stringcopy(field, p - field);
     } else
        hp->port = default_port ? stringcopy(default_port, 0) : NULL;
     return 1;
 }
-    
+
 struct hostportres *newhostport(char *hostport, char *default_port, uint8_t prefixok) {
     struct hostportres *hp;
     char *slash, *s;
     int plen;
-    
+
     hp = malloc(sizeof(struct hostportres));
     if (!hp) {
        debug(DBG_ERR, "resolve_newhostport: malloc failed");
@@ -120,7 +127,7 @@ struct hostportres *newhostport(char *hostport, char *default_port, uint8_t pref
        hp->prefixlen = 255;
     return hp;
 
- errexit:
+errexit:
     freehostport(hp);
     return NULL;
 }
@@ -133,7 +140,7 @@ int resolvehostport(struct hostportres *hp, int socktype, uint8_t passive) {
     hints.ai_family = AF_UNSPEC;
     if (passive)
        hints.ai_flags = AI_PASSIVE;
-    
+
     if (!hp->host && !hp->port) {
        /* getaddrinfo() doesn't like host and port to be NULL */
        if (getaddrinfo(hp->host, "1812" /* can be anything */, &hints, &hp->addrinfo)) {
@@ -167,24 +174,33 @@ int resolvehostport(struct hostportres *hp, int socktype, uint8_t passive) {
     }
     return 1;
 
- errexit:
+errexit:
     if (hp->addrinfo)
        freeaddrinfo(hp->addrinfo);
     return 0;
-}        
+}
 
-int addhostport(struct list **hostports, char *hostport, char *portdefault, uint8_t prefixok) {
+int addhostport(struct list **hostports, char **hostport, char *portdefault, uint8_t prefixok) {
     struct hostportres *hp;
+    int i;
 
-    hp = newhostport(hostport, portdefault, prefixok);
-    if (!hp)
-       return 0;
-    if (!*hostports)
+    if (!*hostports) {
        *hostports = list_create();
-    if (!*hostports || !list_push(*hostports, hp)) {
-       freehostport(hp);
-       debug(DBG_ERR, "addhostport: malloc failed");
-       return 0;
+        if (!*hostports) {
+           debug(DBG_ERR, "addhostport: malloc failed");
+           return 0;
+       }
+    }
+
+    for (i = 0; hostport[i]; i++) {
+       hp = newhostport(hostport[i], portdefault, prefixok);
+       if (!hp)
+           return 0;
+       if (!list_push(*hostports, hp)) {
+           freehostport(hp);
+           debug(DBG_ERR, "addhostport: malloc failed");
+           return 0;
+       }
     }
     return 1;
 }
@@ -200,7 +216,7 @@ void freehostports(struct list *hostports) {
 int resolvehostports(struct list *hostports, int socktype) {
     struct list_node *entry;
     struct hostportres *hp;
-    
+
     for (entry = list_first(hostports); entry; entry = list_next(entry)) {
        hp = (struct hostportres *)entry->data;
        if (!hp->addrinfo && !resolvehostport(hp, socktype, 0))
@@ -232,13 +248,13 @@ static int prefixmatch(void *a1, void *a2, uint8_t len) {
     return (((uint8_t *)a1)[l] & mask[r]) == (((uint8_t *)a2)[l] & mask[r]);
 }
 
-int addressmatches(struct list *hostports, struct sockaddr *addr) {
+int addressmatches(struct list *hostports, struct sockaddr *addr, uint8_t checkport) {
     struct sockaddr_in6 *sa6 = NULL;
     struct in_addr *a4 = NULL;
     struct addrinfo *res;
     struct list_node *entry;
     struct hostportres *hp = NULL;
-    
+
     if (addr->sa_family == AF_INET6) {
         sa6 = (struct sockaddr_in6 *)addr;
         if (IN6_IS_ADDR_V4MAPPED(&sa6->sin6_addr)) {
@@ -253,9 +269,14 @@ int addressmatches(struct list *hostports, struct sockaddr *addr) {
        for (res = hp->addrinfo; res; res = res->ai_next)
            if (hp->prefixlen == 255) {
                if ((a4 && res->ai_family == AF_INET &&
-                    !memcmp(a4, &((struct sockaddr_in *)res->ai_addr)->sin_addr, 4)) ||
+                    !memcmp(a4, &((struct sockaddr_in *)res->ai_addr)->sin_addr, 4) &&
+                    (!checkport || ((struct sockaddr_in *)res->ai_addr)->sin_port ==
+                     ((struct sockaddr_in *)addr)->sin_port)) ||
                    (sa6 && res->ai_family == AF_INET6 &&
-                    !memcmp(&sa6->sin6_addr, &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, 16)))
+                    !memcmp(&sa6->sin6_addr,
+                            &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, 16) &&
+                    (!checkport || ((struct sockaddr_in6 *)res->ai_addr)->sin6_port ==
+                     ((struct sockaddr_in6 *)addr)->sin6_port)))
                    return 1;
            } else {
                if ((a4 && res->ai_family == AF_INET &&
@@ -276,7 +297,7 @@ int connecttcphostlist(struct list *hostports,  struct addrinfo *src) {
     for (entry = list_first(hostports); entry; entry = list_next(entry)) {
        hp = (struct hostportres *)entry->data;
        debug(DBG_WARN, "connecttcphostlist: trying to open TCP connection to %s port %s", hp->host, hp->port);
-       if ((s = connecttcp(hp->addrinfo, src)) >= 0) {
+       if ((s = connecttcp(hp->addrinfo, src, list_count(hostports) > 1 ? 5 : 30)) >= 0) {
            debug(DBG_WARN, "connecttcphostlist: TCP connection to %s port %s up", hp->host, hp->port);
            return s;
        }
@@ -284,3 +305,7 @@ int connecttcphostlist(struct list *hostports,  struct addrinfo *src) {
     debug(DBG_ERR, "connecttcphostlist: failed");
     return -1;
 }
+
+/* Local Variables: */
+/* c-file-style: "stroustrup" */
+/* End: */