]> arthur.barton.de Git - netatalk.git/commitdiff
IPv6 support for afpd and cnid_metad after-ipv6
authorfranklahm <franklahm>
Thu, 5 Nov 2009 14:38:07 +0000 (14:38 +0000)
committerfranklahm <franklahm>
Thu, 5 Nov 2009 14:38:07 +0000 (14:38 +0000)
21 files changed:
etc/afpd/afp_config.c
etc/afpd/afp_options.c
etc/afpd/globals.h
etc/afpd/status.c
etc/afpd/uam.c
etc/afpd/volume.c
etc/cnid_dbd/cnid_metad.c
etc/cnid_dbd/usockfd.c
etc/cnid_dbd/usockfd.h
etc/uams/uams_dhx2_pam.c
etc/uams/uams_dhx_pam.c
etc/uams/uams_dhx_passwd.c
etc/uams/uams_pam.c
etc/uams/uams_passwd.c
include/atalk/dsi.h
include/atalk/util.h
libatalk/cnid/dbd/cnid_dbd.c
libatalk/dsi/dsi_init.c
libatalk/dsi/dsi_private.h
libatalk/dsi/dsi_tcp.c
libatalk/util/socket.c

index a766d26f5a74762f9c3ff7102e6388bd661cc2a6..8c8ac012ad964c79e441d9463869bc4fe096203f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: afp_config.c,v 1.28 2009-10-29 11:35:58 didg Exp $
+ * $Id: afp_config.c,v 1.29 2009-11-05 14:38:07 franklahm Exp $
  *
  * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu)
  * All Rights Reserved.  See COPYRIGHT.
@@ -365,6 +365,11 @@ static AFPConfig *DSIConfigInit(const struct afp_options *options,
         return NULL;
     }
 
+    LOG(log_debug, logtype_afpd, "DSIConfigInit: hostname: %s, ip/port: %s/%s, ",
+        options->hostname,
+        options->ipaddr ? options->ipaddr : "default",
+        options->port ? options->port : "548");
+
     if ((dsi = dsi_init(protocol, "afpd", options->hostname,
                         options->ipaddr, options->port,
                         options->flags & OPTION_PROXY,
@@ -375,13 +380,11 @@ static AFPConfig *DSIConfigInit(const struct afp_options *options,
     }
 
     if (options->flags & OPTION_PROXY) {
-        LOG(log_info, logtype_afpd, "ASIP proxy initialized for %s:%d (%s)",
-            inet_ntoa(dsi->server.sin_addr), ntohs(dsi->server.sin_port),
-            VERSION);
+        LOG(log_info, logtype_afpd, "AFP/TCP proxy initialized for %s:%d (%s)",
+            getip_string((struct sockaddr *)&dsi->server), getip_port((struct sockaddr *)&dsi->server), VERSION);
     } else {
-        LOG(log_info, logtype_afpd, "ASIP started on %s:%d(%d) (%s)",
-            inet_ntoa(dsi->server.sin_addr), ntohs(dsi->server.sin_port),
-            dsi->serversock, VERSION);
+        LOG(log_info, logtype_afpd, "AFP/TCP started, advertising %s:%d (%s)",
+            getip_string((struct sockaddr *)&dsi->server), getip_port((struct sockaddr *)&dsi->server), VERSION);
     }
 
 #ifdef USE_SRVLOC
index ff48c01af720acea2cf1670baaa709ef6b8c8c01..0a1c9e4d6a8516c49ea65ee8d299fe0da2ad50b9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: afp_options.c,v 1.47 2009-10-14 01:38:28 didg Exp $
+ * $Id: afp_options.c,v 1.48 2009-11-05 14:38:07 franklahm Exp $
  *
  * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu)
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
@@ -62,8 +62,8 @@ char *strchr (), *strrchr ();
 #endif /* MIN */
 
 /* FIXME CNID */
-char             Cnid_srv[MAXHOSTNAMELEN + 1] = "localhost";
-int              Cnid_port = 4700;
+const char *Cnid_srv = "localhost";
+const char *Cnid_port = "4700";
 
 #define OPTIONS "dn:f:s:uc:g:P:ptDS:TL:F:U:hIvVm:"
 #define LENGTH 512
@@ -127,6 +127,8 @@ void afp_options_free(struct afp_options *opt,
         free(opt->server);
     if (opt->ipaddr && (opt->ipaddr != save->ipaddr))
         free(opt->ipaddr);
+    if (opt->port && (opt->port != save->port))
+        free(opt->port);
     if (opt->fqdn && (opt->fqdn != save->fqdn))
         free(opt->fqdn);
     if (opt->uampath && (opt->uampath != save->uampath))
@@ -376,18 +378,17 @@ int afp_options_parseline(char *buf, struct afp_options *options)
 
     /* FIXME CNID Cnid_srv is a server attribute */
     if ((c = getoption(buf, "-cnidserver"))) {
-        char *p;
-       int len;        
-        p = strchr(c, ':');
-       if (p != NULL && (len = p - c) <= MAXHOSTNAMELEN) {
-           memcpy(Cnid_srv, c, len);
-           Cnid_srv[len] = 0;
-           Cnid_port = atoi(p +1);
-       }
+        char *p = strrchr(c, ':');
+        if (p)
+            *p = 0;
+        Cnid_srv = strdup(c);
+        if (p)
+            Cnid_port = strdup(p + 1);
+        LOG(log_debug, logtype_afpd, "CNID Server: %s:%s", Cnid_srv, Cnid_port);
     }
 
     if ((c = getoption(buf, "-port")))
-        options->port = atoi(c);
+        options->port = strdup(c);
     if ((c = getoption(buf, "-ddpaddr")))
         atalk_aton(c, &options->ddpaddr);
     if ((c = getoption(buf, "-signature")) && (opt = strdup(c)))
@@ -651,7 +652,7 @@ int afp_options_parse(int ac, char **av, struct afp_options *options)
             options->transports &= ~AFPTRANS_DDP;
             break;
         case 'S':
-            options->port = atoi(optarg);
+            options->port = optarg;
             break;
         case 'T':
             options->transports &= ~AFPTRANS_TCP;
index 2ab33e6606aafa196053bd2a432755be1e293522..c1f8986e8da8ab7fac16ae6117390229e13afae3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: globals.h,v 1.29 2009-10-25 07:18:12 didg Exp $
+ * $Id: globals.h,v 1.30 2009-11-05 14:38:07 franklahm Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -56,10 +56,10 @@ struct afp_volume_name {
 };
 
 struct afp_options {
-    int connections, port, transports, tickleval, timeout, server_notif, flags;
+    int connections, transports, tickleval, timeout, server_notif, flags;
     unsigned char passwdbits, passwdminlen, loginmaxfail;
     u_int32_t server_quantum;
-    char hostname[MAXHOSTNAMELEN + 1], *server, *ipaddr, *configfile;
+    char hostname[MAXHOSTNAMELEN + 1], *server, *ipaddr, *port, *configfile;
     struct at_addr ddpaddr;
     char *uampath, *fqdn;
     char *pidfile;
@@ -119,8 +119,8 @@ extern struct dir   *curdir;
 extern char            getwdbuf[];
 
 /* FIXME CNID */
-extern char             Cnid_srv[MAXHOSTNAMELEN + 1];
-extern int              Cnid_port;
+extern const char *Cnid_srv;
+extern const char *Cnid_port;
 
 extern int  get_afp_errno   (const int param);
 extern void afp_options_init (struct afp_options *);
index e661538d815078000c961f562ca36db5c01c7358..745d349c5765768ce49960dfbd121312d55f97a0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: status.c,v 1.26 2009-10-29 11:35:58 didg Exp $
+ * $Id: status.c,v 1.27 2009-11-05 14:38:07 franklahm Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -203,9 +203,15 @@ server_signature_hostid:
     hostid = gethostid();
 #endif /* BSD4_4 && !HAVE_GETHOSTID */
     if (!hostid) {
-        if (dsi)
-            hostid = dsi->server.sin_addr.s_addr;
-        else {
+        if (dsi) {
+            if (dsi->server.ss_family == AF_INET) { /* IPv4 */
+                hostid = ((struct sockaddr_in *)(&dsi->server))->sin_addr.s_addr;
+            } else {                                /* IPv6 */
+                struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)&dsi->server;
+                /* Use the last "sizeof(long) bytes of the IPv6 addr */
+                memcpy(&hostid, sa6->sin6_addr.s6_addr + (16 - sizeof(long)), sizeof(long));
+            }
+        } else {
             struct hostent *host;
 
             if ((host = gethostbyname(options->hostname)))
@@ -261,25 +267,45 @@ static size_t status_netaddress(char *data, int *servoffset,
 
     /* ip address */
     if (dsi) {
-        const struct sockaddr_in *inaddr = &dsi->server;
-
-        if (inaddr->sin_port == htons(DSI_AFPOVERTCP_PORT)) {
-            *data++ = 6; /* length */
-            *data++ = 0x01; /* basic ip address */
-            memcpy(data, &inaddr->sin_addr.s_addr,
-                   sizeof(inaddr->sin_addr.s_addr));
-            data += sizeof(inaddr->sin_addr.s_addr);
-            addresses_len += 7;
-        } else {
-            /* ip address + port */
-            *data++ = 8;
-            *data++ = 0x02; /* ip address with port */
-            memcpy(data, &inaddr->sin_addr.s_addr,
-                   sizeof(inaddr->sin_addr.s_addr));
-            data += sizeof(inaddr->sin_addr.s_addr);
-            memcpy(data, &inaddr->sin_port, sizeof(inaddr->sin_port));
-            data += sizeof(inaddr->sin_port);
-            addresses_len += 9;
+        if (dsi->server.ss_family == AF_INET) { /* IPv4 */
+            const struct sockaddr_in *inaddr = (struct sockaddr_in *)&dsi->server;
+            if (inaddr->sin_port == htons(DSI_AFPOVERTCP_PORT)) {
+                *data++ = 6; /* length */
+                *data++ = 0x01; /* basic ip address */
+                memcpy(data, &inaddr->sin_addr.s_addr,
+                       sizeof(inaddr->sin_addr.s_addr));
+                data += sizeof(inaddr->sin_addr.s_addr);
+                addresses_len += 7;
+            } else {
+                /* ip address + port */
+                *data++ = 8;
+                *data++ = 0x02; /* ip address with port */
+                memcpy(data, &inaddr->sin_addr.s_addr,
+                       sizeof(inaddr->sin_addr.s_addr));
+                data += sizeof(inaddr->sin_addr.s_addr);
+                memcpy(data, &inaddr->sin_port, sizeof(inaddr->sin_port));
+                data += sizeof(inaddr->sin_port);
+                addresses_len += 9;
+            }
+        } else { /* IPv6 */
+            const struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)&dsi->server;
+            if (sa6->sin6_port == htons(DSI_AFPOVERTCP_PORT)) {
+                *data++ = 18; /* length */
+                *data++ = 6; /* type */
+                memcpy(data, &sa6->sin6_addr.s6_addr, sizeof(sa6->sin6_addr.s6_addr));
+                data += sizeof(sa6->sin6_addr.s6_addr);
+                addresses_len += 19;
+            } else {
+                /* ip address + port */
+                *data++ = 20; /* length */
+                *data++ = 7; /* type*/
+                memcpy(data, &sa6->sin6_addr.s6_addr, sizeof(sa6->sin6_addr.s6_addr));
+                data += sizeof(sa6->sin6_addr.s6_addr);
+                memcpy(data, &sa6->sin6_port, sizeof(sa6->sin6_port));
+                data += sizeof(sa6->sin6_port);
+                addresses_len += 21;
+            }
+
         }
     }
 
@@ -486,7 +512,7 @@ void status_init(AFPConfig *aspconfig, AFPConfig *dsiconfig,
     DSI *dsi;
     char *status = NULL;
     size_t statuslen;
-    int c, sigoff;
+    int c, sigoff, ipok;
 
     if (!(aspconfig || dsiconfig) || !options)
         return;
@@ -502,6 +528,19 @@ void status_init(AFPConfig *aspconfig, AFPConfig *dsiconfig,
         status = dsiconfig->status;
         maxstatuslen=sizeof(dsiconfig->status);
         dsi = dsiconfig->obj.handle;
+        if (dsi->server.ss_family == AF_INET) { /* IPv4 */
+            const struct sockaddr_in *sa4 = (struct sockaddr_in *)&dsi->server;
+            ipok = sa4->sin_addr.s_addr ? 1 : 0;
+        } else { /* IPv6 */
+            const struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)&dsi->server;
+            ipok = 0;
+            for (int i=0; i<16; i++) {
+                if (sa6->sin6_addr.s6_addr[i]) {
+                    ipok = 1;
+                    break;
+                }
+            }
+        }
     } else
         dsi = NULL;
 
@@ -525,11 +564,12 @@ void status_init(AFPConfig *aspconfig, AFPConfig *dsiconfig,
      * (16-bytes), network addresses, volume icon/mask 
      */
 
-    status_flags(status, options->server_notif, options->fqdn ||
-                 (dsiconfig && dsi->server.sin_addr.s_addr),
+    status_flags(status,
+                 options->server_notif,
+                 (options->fqdn || ipok),
                  options->passwdbits, 
-                (options->k5service && options->k5realm && options->fqdn), 
-                options->flags);
+                 (options->k5service && options->k5realm && options->fqdn),
+                 options->flags);
     /* returns offset to signature offset */
     c = status_server(status, options->server ? options->server :
                       options->hostname, options);
index 1ac037e6b939b35a0d833c319f27a19fa00e748d..7d5ed70111d08ecb57a531b72b04fbaa9ca12054 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: uam.c,v 1.31 2009-10-29 11:35:58 didg Exp $
+ * $Id: uam.c,v 1.32 2009-11-05 14:38:07 franklahm Exp $
  *
  * Copyright (c) 1999 Adrian Sun (asun@zoology.washington.edu)
  * All Rights Reserved.  See COPYRIGHT.
@@ -365,8 +365,8 @@ int uam_random_string (AFPObj *obj, char *buf, int len)
 int uam_afpserver_option(void *private, const int what, void *option,
                          size_t *len)
 {
-AFPObj *obj = private;
-    char **buf = (char **) option; /* most of the options are this */
+    AFPObj *obj = private;
+    const char **buf = (const char **) option; /* most of the options are this */
     struct session_info **sinfo = (struct session_info **) option;
 
     if (!obj || !option)
@@ -436,19 +436,19 @@ AFPObj *obj = private;
         break;
         
     case UAM_OPTION_CLIENTNAME:
-        {
-            struct DSI *dsi = obj->handle;
-            struct hostent *hp;
-
-            hp = gethostbyaddr( (char *) &dsi->client.sin_addr,
-                                sizeof( struct in_addr ),
-                                dsi->client.sin_family );
-            if( hp )
-                *buf = hp->h_name;
-            else
-                *buf = inet_ntoa( dsi->client.sin_addr );
-        }
+    {
+        struct DSI *dsi = obj->handle;
+        const struct sockaddr *sa;
+        char hbuf[NI_MAXHOST];
+        
+        sa = (struct sockaddr *)&dsi->client;
+        if (getnameinfo(sa, sizeof(dsi->client), hbuf, sizeof(hbuf), NULL, 0, 0) == 0)
+            *buf = hbuf;
+        else
+            *buf = getip_string((struct sockaddr *)&dsi->client);
+
         break;
+    }
     case UAM_OPTION_COOKIE:
         /* it's up to the uam to actually store something useful here.
          * this just passes back a handle to the cookie. the uam side
index 13f4afa50f78ae47eed8abb3ed991764f5d42b22..2226b7185b65da5bcd7912afa0b73c91874772e9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: volume.c,v 1.97 2009-10-29 10:55:46 franklahm Exp $
+ * $Id: volume.c,v 1.98 2009-11-05 14:38:07 franklahm Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -242,7 +242,8 @@ static void volfree(struct vol_option *options,
 static char *volxlate(AFPObj *obj, char *dest, size_t destlen,
                      char *src, struct passwd *pwd, char *path, char *volname)
 {
-    char *p, *q;
+    char *p, *r;
+    const char *q;
     int len;
     char *ret;
     
@@ -288,17 +289,17 @@ static char *volxlate(AFPObj *obj, char *dest, size_t destlen,
 
             } else if (obj->proto == AFPPROTO_DSI) {
                 DSI *dsi = obj->handle;
-
-                len = sprintf(dest, "%s:%u", inet_ntoa(dsi->client.sin_addr),
-                              ntohs(dsi->client.sin_port));
+                len = sprintf(dest, "%s:%u",
+                              getip_string((struct sockaddr *)&dsi->client),
+                              getip_port((struct sockaddr *)&dsi->client));
                 dest += len;
                 destlen -= len;
             }
         } else if (is_var(p, "$d")) {
              q = path;
         } else if (is_var(p, "$f")) {
-            if ((q = strchr(pwd->pw_gecos, ',')))
-                *q = '\0';
+            if ((r = strchr(pwd->pw_gecos, ',')))
+                *r = '\0';
             q = pwd->pw_gecos;
         } else if (is_var(p, "$g")) {
             struct group *grp = getgrgid(pwd->pw_gid);
@@ -316,9 +317,8 @@ static char *volxlate(AFPObj *obj, char *dest, size_t destlen,
  
             } else if (obj->proto == AFPPROTO_DSI) {
                 DSI *dsi = obj->handle;
-                q = inet_ntoa(dsi->client.sin_addr);
-            }
+                q = getip_string((struct sockaddr *)&dsi->client);
+           }
         } else if (is_var(p, "$s")) {
             if (obj->Obj)
                 q = obj->Obj;
@@ -885,10 +885,12 @@ static int accessvol(const char *args, const char *name)
     return 0;
 }
 
-static int hostaccessvol(int type, char *volname, const char *args, const AFPObj *obj)
+static int hostaccessvol(int type, const char *volname, const char *args, const AFPObj *obj)
 {
+    int mask_int;
     char buf[MAXPATHLEN + 1], *p, *b;
     DSI *dsi = obj->handle;
+    struct sockaddr_storage client;
 
     if (!args)
         return -1;
@@ -897,36 +899,57 @@ static int hostaccessvol(int type, char *volname, const char *args, const AFPObj
     if ((p = strtok_r(buf, ",", &b)) == NULL) /* nothing, return okay */
         return -1;
 
+    if (obj->proto != AFPPROTO_DSI)
+        return -1;
+
     while (p) {
-        if (obj->proto == AFPPROTO_DSI) {
-            struct in_addr mask, net;
-            char *net_char, *mask_char;
-            int mask_int;
-
-            net_char = strtok(p, "/");
-            mask_char = strtok(NULL,"/");
-            if (mask_char == NULL) {
+        int ret;
+        char *ipaddr, *mask_char;
+        struct addrinfo hints, *ai;
+
+        ipaddr = strtok(p, "/");
+        mask_char = strtok(NULL,"/");
+
+        /* Get address from string with getaddrinfo */
+        memset(&hints, 0, sizeof hints);
+        hints.ai_family = AF_UNSPEC;
+        hints.ai_socktype = SOCK_STREAM;
+        if ((ret = getaddrinfo(ipaddr, NULL, &hints, &ai)) != 0) {
+            LOG(log_error, logtype_afpd, "hostaccessvol: getaddrinfo: %s\n", gai_strerror(ret));
+            continue;
+        }        
+
+        /* netmask */
+        if (mask_char != NULL)
+            mask_int = atoi(mask_char); /* apply_ip_mask does range checking on it */
+        else {
+            if (ai->ai_family == AF_INET) /* IPv4 */
                 mask_int = 32;
-            } else {
-                mask_int = atoi(mask_char);
-            }
-           
-            // convert the integer netmask to a bitmask in network order
-            mask.s_addr = htonl(-1 - ((1 << (32 - mask_int)) - 1));
-            net.s_addr = inet_addr(net_char) & mask.s_addr;
-
-            if ((dsi->client.sin_addr.s_addr & mask.s_addr) == net.s_addr) {
-                   if (type == VOLOPT_DENIED_HOSTS)
-                       LOG(log_info, logtype_afpd, "AFP access denied for client IP '%s' to volume '%s' by denied list",
-                           inet_ntoa(dsi->client.sin_addr), volname);
-                   return 1;
-           }
+            else                          /* IPv6 */
+                mask_int = 128;
+        }
+
+        /* Apply mask to addresses */
+        client = dsi->client;
+        apply_ip_mask((struct sockaddr *)&client, mask_int);
+        apply_ip_mask(ai->ai_addr, mask_int);
+
+        if (compare_ip((struct sockaddr *)&client, ai->ai_addr) == 0) {
+            if (type == VOLOPT_DENIED_HOSTS)
+                LOG(log_info, logtype_afpd, "AFP access denied for client IP '%s' to volume '%s' by denied list",
+                    getip_string((struct sockaddr *)&client), volname);
+            freeaddrinfo(ai);
+            return 1;
         }
+
+        /* next address */
+        freeaddrinfo(ai);
         p = strtok_r(NULL, ",", &b);
     }
+
     if (type == VOLOPT_ALLOWED_HOSTS)
-       LOG(log_info, logtype_afpd, "AFP access denied for client IP '%s' to volume '%s', not in allowed list",
-           inet_ntoa(dsi->client.sin_addr), volname);
+        LOG(log_info, logtype_afpd, "AFP access denied for client IP '%s' to volume '%s', not in allowed list",
+            getip_string((struct sockaddr *)&dsi->client), volname);
     return 0;
 }
 
@@ -1182,9 +1205,9 @@ static int readvolfile(AFPObj *obj, struct afp_volume_name *p1, char *p2, int us
                allow -> either no list (-1), or in list (1)
                deny -> either no list (-1), or not in list (0) */
             if (accessvol(options[VOLOPT_ALLOW].c_value, obj->username) &&
-               (accessvol(options[VOLOPT_DENY].c_value, obj->username) < 1) &&
-               hostaccessvol(VOLOPT_ALLOWED_HOSTS, volname, options[VOLOPT_ALLOWED_HOSTS].c_value, obj) &&
-               (hostaccessvol(VOLOPT_DENIED_HOSTS, volname, options[VOLOPT_DENIED_HOSTS].c_value, obj) < 1)) {
+                (accessvol(options[VOLOPT_DENY].c_value, obj->username) < 1) &&
+                hostaccessvol(VOLOPT_ALLOWED_HOSTS, volname, options[VOLOPT_ALLOWED_HOSTS].c_value, obj) &&
+                (hostaccessvol(VOLOPT_DENIED_HOSTS, volname, options[VOLOPT_DENIED_HOSTS].c_value, obj) < 1)) {
 
                 /* handle read-only behaviour. semantics:
                  * 1) neither the rolist nor the rwlist exist -> rw
@@ -2463,8 +2486,9 @@ static int savevoloptions (const struct vol *vol)
     strlcat(buf, Cnid_srv, sizeof(buf));
     strlcat(buf, "\n", sizeof(buf));
 
-    snprintf(item, sizeof(item), "CNIDDBDPORT:%u\n", Cnid_port);
-    strlcat(buf, item, sizeof(buf));
+    strlcat(buf, "CNIDDBDPORT:", sizeof(buf));
+    strlcat(buf, Cnid_port, sizeof(buf));
+    strlcat(buf, "\n", sizeof(buf));
 
     strcpy(item, "CNID_DBPATH:");
     if (vol->v_dbpath)
index a383522ee9cd58806bd0dfa2b742d8970dddd69c..d6b62469bcefe066bfdfa6701d665f1ce8f93df9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: cnid_metad.c,v 1.20 2009-10-29 11:19:23 didg Exp $
+ * $Id: cnid_metad.c,v 1.21 2009-11-05 14:38:07 franklahm Exp $
  *
  * Copyright (C) Joerg Lenneis 2003
  * All Rights Reserved.  See COPYING.
 #include "config.h"
 #endif /* HAVE_CONFIG_H */
 
-#include <stdlib.h>
-
-#ifdef HAVE_UNISTD_H
-#undef _USE_GNU_SOURCE
-#define _USE_GNU_SOURCE
+#ifdef linux
+#define _GNU_SOURCE
+#endif
 #include <unistd.h>
 #undef __USE_GNU
-#endif /* HAVE_UNISTD_H */
+
+#include <stdlib.h>
 #include <sys/param.h>
 #include <errno.h>
 #include <string.h>
 #define USE_SETRESUID 1
 #define SWITCH_TO_GID(gid)  ((setresgid(gid,gid,gid) < 0 || setgid(gid) < 0) ? -1 : 0)
 #define SWITCH_TO_UID(uid)  ((setresuid(uid,uid,uid) < 0 || setuid(uid) < 0) ? -1 : 0)
-#endif
-#else
+#endif  /* USE_SETRESUID */
+#else   /* ! linux */
 #ifndef USE_SETEUID
 #define USE_SETEUID 1
 #define SWITCH_TO_GID(gid)  ((setegid(gid) < 0 || setgid(gid) < 0) ? -1 : 0)
 #define SWITCH_TO_UID(uid)  ((setuid(uid) < 0 || seteuid(uid) < 0 || setuid(uid) < 0) ? -1 : 0)
-#endif
-#endif
+#endif  /* USE_SETEUID */
+#endif  /* linux */
 
 #include <atalk/util.h>
 #include <atalk/logger.h>
@@ -115,7 +114,7 @@ static volatile sig_atomic_t sigchild = 0;
                                         * to reconnect every 5 secondes, catch it */
 #define MAXVOLS    512
 #define DEFAULTHOST  "localhost"
-#define DEFAULTPORT  4700
+#define DEFAULTPORT  "4700"
 
 struct server {
     char  *name;
@@ -416,7 +415,7 @@ int main(int argc, char *argv[])
     int   status;
     char  *dbdpn = _PATH_CNID_DBD;
     char  *host = DEFAULTHOST;
-    u_int16_t   port = DEFAULTPORT;
+    char  *port = DEFAULTPORT;
     struct db_param *dbp;
     int    i;
     int    cc;
@@ -454,7 +453,7 @@ int main(int argc, char *argv[])
             }
             break;
         case 'p':
-            port = atoi(optarg);
+            port = strdup(optarg);
             break;
         case 's':
             dbdpn = strdup(optarg);
index 888d914b39bf1fcb23bac0625cdc24037d31afd7..6c97fe73b56ea1925402720c9988523378b3fcf3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: usockfd.c,v 1.5 2009-10-18 20:21:09 didg Exp $
+ * $Id: usockfd.c,v 1.6 2009-11-05 14:38:07 franklahm Exp $
  *
  * Copyright (C) Joerg Lenneis 2003
  * All Rights Reserved.  See COPYING.
@@ -78,63 +78,72 @@ int usockfd_create(char *usock_fn, mode_t mode, int backlog)
 }
 
 /* ---------------
-   create a tcp socket (should share dsi stuff)
-*/
-int tsockfd_create(char *host, u_int16_t ipport, int backlog)
+ * create a tcp socket
+ */
+int tsockfd_create(char *host, char *port, int backlog)
 {
-    int sockfd;
-    struct sockaddr_in server;
-    struct hostent     *hp;  
-    int                port;
-    
-    hp=gethostbyname(host);
-    if (!hp) {
-        unsigned long int addr=inet_addr(host);
-        if (addr!= (unsigned)-1)
-            hp=gethostbyaddr((char*)addr,sizeof(addr),AF_INET);
-        if (!hp) {
-            LOG(log_error, logtype_cnid, "gethostbyaddr %s: %s", host, strerror(errno));
-            return -1;
-        }
-    }
-    memcpy((char*)&server.sin_addr,(char*)hp->h_addr,sizeof(server.sin_addr));    
+    int sockfd, flag, ret;
+    struct addrinfo hints, *servinfo, *p;
 
-    if ((sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
-        LOG(log_error, logtype_cnid, "error in socket call: %s", strerror(errno));
-        return -1;
+    /* Prepare hint for getaddrinfo */
+    memset(&hints, 0, sizeof hints);
+    hints.ai_family = AF_UNSPEC;
+    hints.ai_socktype = SOCK_STREAM;
+
+    if ((ret = getaddrinfo(host, port, &hints, &servinfo)) != 0) {
+        LOG(log_error, logtype_default, "tsockfd_create: getaddrinfo: %s\n", gai_strerror(ret));
+        return 0;
     }
-     
-    port = htons(ipport);
-    
-    server.sin_family = AF_INET;
-    server.sin_port = port;
 
+    /* create a socket */
+    /* loop through all the results and bind to the first we can */
+    for (p = servinfo; p != NULL; p = p->ai_next) {
+        if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
+            LOG(log_info, logtype_default, "tsockfd_create: socket: %s", strerror(errno));
+            continue;
+        }
+
+        /*
+         * Set some socket options:
+         * SO_REUSEADDR deals w/ quick close/opens
+         * TCP_NODELAY diables Nagle
+         */
 #ifdef SO_REUSEADDR
-    port = 1;
-    setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &port, sizeof(port));
-#endif /* SO_REUSEADDR */
+        flag = 1;
+        setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag));
+#endif
 
-#ifdef USE_TCP_NODELAY 
+#ifdef USE_TCP_NODELAY
 #ifndef SOL_TCP
 #define SOL_TCP IPPROTO_TCP
-#endif /* ! SOL_TCP */
-    port = 1;
-    setsockopt(sockfd, SOL_TCP, TCP_NODELAY, &port, sizeof(port));
+#endif
+        flag = 1;
+        setsockopt(sockfd, SOL_TCP, TCP_NODELAY, &flag, sizeof(flag));
 #endif /* USE_TCP_NODELAY */
+            
+        if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
+            close(sockfd);
+            LOG(log_info, logtype_default, "tsockfd_create: bind: %s\n", strerror(errno));
+            continue;
+        }
 
-    if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0) {
-        LOG(log_error, logtype_cnid, "error binding to socket for %s: %s",
-            host, strerror(errno));
-        return -1;
+        if (listen(sockfd, backlog) < 0) {
+            close(sockfd);
+            LOG(log_info, logtype_default, "tsockfd_create: listen: %s\n", strerror(errno));
+            continue;
+        }
+
+        /* We got a socket */
+        break;
     }
 
-    if (listen(sockfd, backlog) < 0) {
-        LOG(log_error, logtype_cnid, "error in listen for %s: %s",
-            host, strerror(errno));
+    if (p == NULL)  {
+        LOG(log_error, logtype_default, "tsockfd_create: no suitable network config %s:%s", host, port);
+        freeaddrinfo(servinfo);
         return -1;
     }
 
+    freeaddrinfo(servinfo);
     return sockfd;
 }
 
index 622282e7277c7a7b7792cbe0b324d199a8c1db56..ee4d4327a77100bc247b7b28f7848266542c3338 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: usockfd.h,v 1.4 2009-10-18 19:02:43 didg Exp $
+ * $Id: usockfd.h,v 1.5 2009-11-05 14:38:07 franklahm Exp $
  *
  * Copyright (C) Joerg Lenneis 2003
  * All Rights Reserved.  See COPYING.
@@ -14,7 +14,7 @@
 
 
 extern int      usockfd_create  (char *, mode_t, int);
-extern int      tsockfd_create  (char *, u_int16_t, int);
+extern int      tsockfd_create  (char *, char *, int);
 extern int      usockfd_check   (int, const sigset_t *);
 
 #ifndef OSSH_ALIGNBYTES
index 48c407c72f7c412e0ab1d9c6d71c8813fa69fb42..dae84673a3ea8935c373fe284cb6419b358a58a1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: uams_dhx2_pam.c,v 1.8 2009-10-15 11:39:48 didg Exp $
+ * $Id: uams_dhx2_pam.c,v 1.9 2009-11-05 14:38:07 franklahm Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * Copyright (c) 1999 Adrian Sun (asun@u.washington.edu)
@@ -566,7 +566,7 @@ static int logincont2(void *obj, struct passwd **uam_pwd,
 {
     int ret;
     int PAM_error;
-    char *hostname = NULL;
+    const char *hostname = NULL;
     gcry_mpi_t retServerNonce;
     gcry_cipher_hd_t ctx;
     gcry_error_t ctxerror;
@@ -753,7 +753,7 @@ static int changepw_3(void *obj _U_,
     int PAM_error;
     uid_t uid;
     pam_handle_t *lpamh;
-    char *hostname = NULL;
+    const char *hostname = NULL;
     gcry_mpi_t retServerNonce;
     gcry_cipher_hd_t ctx;
     gcry_error_t ctxerror;
index ec3501f14fb37e3e99961a5d3e8bb158846dd3bc..7b9ee0a16ae7c04b1ffcb3080a9a630a385d5179 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: uams_dhx_pam.c,v 1.31 2009-10-15 11:39:48 didg Exp $
+ * $Id: uams_dhx_pam.c,v 1.32 2009-11-05 14:38:07 franklahm Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * Copyright (c) 1999 Adrian Sun (asun@u.washington.edu) 
@@ -410,7 +410,7 @@ static int pam_logincont(void *obj, struct passwd **uam_pwd,
                         char *ibuf, size_t ibuflen _U_, 
                         char *rbuf, size_t *rbuflen)
 {
-    char *hostname;
+    const char *hostname;
     BIGNUM *bn1, *bn2, *bn3;
     u_int16_t sessid;
     int err, PAM_error;
index 6c55a8186088e32a09f106233cf2853d9f81ff56..6abbab0a88e3c4d9337e3e1af5c56fab366f9529 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: uams_dhx_passwd.c,v 1.26 2009-10-22 13:40:11 franklahm Exp $
+ * $Id: uams_dhx_passwd.c,v 1.27 2009-11-05 14:38:07 franklahm Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * Copyright (c) 1999 Adrian Sun (asun@u.washington.edu) 
@@ -70,7 +70,7 @@ static u_int8_t randbuf[16];
 #include <sia.h>
 #include <siad.h>
 
-static char *clientname;
+static const char *clientname;
 #endif /* TRU64 */
 
 /* dhx passwd */
index 37597f75bea20cbdea532e6df40f90b3c978d6d6..25ee5814b3ae440231bea067e65025fba1fe1f4e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: uams_pam.c,v 1.21 2009-10-15 11:39:48 didg Exp $
+ * $Id: uams_pam.c,v 1.22 2009-11-05 14:38:07 franklahm Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * Copyright (c) 1999 Adrian Sun (asun@u.washington.edu) 
@@ -55,7 +55,7 @@ char *strchr (), *strrchr ();
  * and the server_login function
  */
 static pam_handle_t *pamh = NULL; 
-static char *hostname;
+static const char *hostname;
 static char *PAM_username;
 static char *PAM_password;
 
index 66dd2d142c44126f777b532133fda5b600682ff9..3e8333b0fc80252798979833b4206ba5f3590ea0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: uams_passwd.c,v 1.27 2009-10-15 11:39:48 didg Exp $
+ * $Id: uams_passwd.c,v 1.28 2009-11-05 14:38:07 franklahm Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * Copyright (c) 1999 Adrian Sun (asun@u.washington.edu) 
@@ -68,7 +68,7 @@ char *strchr (), *strrchr ();
 #include <sia.h>
 #include <siad.h>
 
-static char *clientname;
+static const char *clientname;
 #endif /* TRU64 */
 
 /*XXX in etc/papd/file.h */
index 058b7d36329b2f182c0f568ab1de59eaeac51c1e..fb45a30e0563dd9135053291cf42e7bd946a6c12 100644 (file)
@@ -56,7 +56,7 @@ struct dsi_block {
 typedef struct DSI {
   dsi_proto protocol;
   struct dsi_block header;
-  struct sockaddr_in server, client;
+  struct sockaddr_storage server, client;
   
   struct itimerval timer;
 
@@ -144,7 +144,7 @@ typedef struct DSI {
 extern DSI *dsi_init (const dsi_proto /*protocol*/,
                          const char * /*program*/, 
                          const char * /*host*/, const char * /*address*/,
-                         const int /*port*/, const int /*proxy*/,
+                         const char * /*port*/, const int /*proxy*/,
                          const u_int32_t /* server quantum */);
 extern void dsi_setstatus (DSI *, char *, const size_t);
 
index 4e05b07e5bd25282ca97db85b8409ab7a341100a..670a7439dfc179bd045663b95b77929d3e1950b8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: util.h,v 1.12 2009-10-26 12:35:56 franklahm Exp $
+ * $Id: util.h,v 1.13 2009-11-05 14:38:08 franklahm Exp $
  */
 
 #ifndef _ATALK_UTIL_H
@@ -159,3 +159,77 @@ extern int lock_reg(int fd, int cmd, int type, off_t offest, int whence, off_t l
  * fd's file flags.
  */
 extern int setnonblock(int fd, int cmd);
+
+/* 
+ * Function: getip_string
+ *
+ * Purpose: convert an IPv4 or IPv6 address to a static string using inet_ntop
+ *
+ * Arguments:
+ *
+ *   sa        (r) pointer to an struct sockaddr
+ *
+ * Returns: pointer to a static string cotaining the converted address as string.
+ *          On error pointers to "0.0.0.0" or "::0" are returned.
+ *
+ * Effects:
+ *
+ * IPv6 mapped IPv4 addresses are returned as IPv4 addreses eg
+ * ::ffff:10.0.0.0 is returned as "10.0.0.0".
+ */
+extern const char *getip_string(const struct sockaddr *sa);
+
+/* 
+ * Function: getip_string
+ *
+ * Purpose: return port number from struct sockaddr
+ *
+ * Arguments:
+ *
+ *   sa        (r) pointer to an struct sockaddr
+ *
+ * Returns: port as unsigned int
+ *
+ * Effects: none.
+ */
+extern unsigned int getip_port(const struct sockaddr *sa);
+
+/* 
+ * Function: apply_ip_mask
+ *
+ * Purpose: apply netmask to IP (v4 or v6)
+ *
+ * Arguments:
+ *
+ *   ai        (rw) pointer to an struct sockaddr
+ *   mask      (r) number of maskbits
+ *
+ * Returns: void
+ *
+ * Effects: 
+ *
+ * Modifies IP address in sa->sin[6]_addr-s[6]_addr. The caller is responsible
+ * for passing a value for mask that is sensible to the passed address,
+ * eg 0 <= mask <= 32 for IPv4 or 0<= mask <= 128 for IPv6. mask > 32 for
+ * IPv4 is treated as mask = 32, mask > 128 is set to 128 for IPv6.
+ */
+extern void apply_ip_mask(struct sockaddr *ai, int maskbits);
+
+/* 
+ * Function: compare_ip
+ *
+ * Purpose: Compare IP addresses for equality
+ *
+ * Arguments:
+ *
+ *   sa1       (r) pointer to an struct sockaddr
+ *   sa2       (r) pointer to an struct sockaddr
+ *
+ * Returns: Addresses are converted to strings and compared with strcmp and
+ *          the result of strcmp is returned.
+ *
+ * Effects: 
+ *
+ * IPv6 mapped IPv4 addresses are treated as IPv4 addresses.
+ */
+extern int compare_ip(const struct sockaddr *sa1, const struct sockaddr *sa2);
index 837c62e3dbf3c3000508aefad24beb825607452a..6fff3bf3d0e934ed0a65b322f809233ab7c00049 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: cnid_dbd.c,v 1.10 2009-10-19 11:00:28 didg Exp $
+ * $Id: cnid_dbd.c,v 1.11 2009-11-05 14:38:08 franklahm Exp $
  *
  * Copyright (C) Joerg Lenneis 2003
  * All Rights Reserved.  See COPYING.
@@ -52,8 +52,8 @@ static void RQST_RESET(struct cnid_dbd_rqst  *r)
 }
 
 /* ----------- */
-extern char             Cnid_srv[MAXHOSTNAMELEN + 1];
-extern int              Cnid_port;
+extern char *Cnid_srv;
+extern char *Cnid_port;
 
 #define MAX_DELAY 40
 
@@ -69,78 +69,81 @@ static void delay(int sec)
     select(0, NULL, NULL, NULL, &tv);
 }
 
-static int tsock_getfd(char *host, int port)
+static int tsock_getfd(const char *host, const char *port)
 {
-    int sock;
-    struct sockaddr_in server;
-    struct hostent* hp;
+    int sock = -1;
     struct timeval tv;
     int attr;
     int err;
+    struct addrinfo hints, *servinfo, *p;
 
-    server.sin_family=AF_INET;
-    server.sin_port=htons((unsigned short)port);
-    if (!host) {
-        LOG(log_error, logtype_cnid, "getfd: -cnidserver not defined");
+    /* Prepare hint for getaddrinfo */
+    memset(&hints, 0, sizeof hints);
+    hints.ai_family = AF_UNSPEC;
+    hints.ai_socktype = SOCK_STREAM;
+    hints.ai_flags = AI_NUMERICSERV;
+
+    if ((err = getaddrinfo(host, port, &hints, &servinfo)) != 0) {
+        LOG(log_error, logtype_default, "tsock_getfd: getaddrinfo: %s:%s : %s\n", host, port, gai_strerror(err));
         return -1;
     }
 
-    hp=gethostbyname(host);
-    if (!hp) {
-        unsigned long int addr=inet_addr(host);
-        LOG(log_warning, logtype_cnid, "getfd: Could not resolve host %s, trying numeric address instead", host);
-        if (addr!= (unsigned)-1)
-            hp=gethostbyaddr((char*)addr,sizeof(addr),AF_INET);
+    /* loop through all the results and bind to the first we can */
+    for (p = servinfo; p != NULL; p = p->ai_next) {
+        if ((sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
+            LOG(log_info, logtype_default, "tsock_getfd: socket %s:: %s", host, strerror(errno));
+                continue;
+        }
 
-        if (!hp) {
-            LOG(log_error, logtype_cnid, "getfd: Could not resolve host %s", host);
-            return(-1);
+        attr = 1;
+        if (setsockopt(sock, SOL_TCP, TCP_NODELAY, &attr, sizeof(attr)) == -1) {
+            LOG(log_error, logtype_cnid, "getfd: set TCP_NODELAY %s: %s", host, strerror(errno));
+            close(sock);
+            continue;
+        }
+        
+        tv.tv_sec = SOCK_DELAY;
+        tv.tv_usec = 0;
+        if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
+            LOG(log_error, logtype_cnid, "getfd: set SO_RCVTIMEO %s: %s", host, strerror(errno));
+            close(sock);
+            continue;
         }
-    }
-    memcpy((char*)&server.sin_addr,(char*)hp->h_addr,sizeof(server.sin_addr));
-    sock=socket(PF_INET,SOCK_STREAM,0);
-    if (sock==-1) {
-        LOG(log_error, logtype_cnid, "getfd: socket %s: %s", host, strerror(errno));
-        return(-1);
-    }
-    attr = 1;
-    if (setsockopt(sock, SOL_TCP, TCP_NODELAY, &attr, sizeof(attr)) == -1) {
-        LOG(log_error, logtype_cnid, "getfd: set TCP_NODELAY %s: %s", host, strerror(errno));
-        close(sock);
-        return(-1);
-    }
 
-    tv.tv_sec = SOCK_DELAY;
-    tv.tv_usec = 0;
-    if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
-        LOG(log_error, logtype_cnid, "getfd: set SO_RCVTIMEO %s: %s", host, strerror(errno));
-        close(sock);
-        return(-1);
+        tv.tv_sec = SOCK_DELAY;
+        tv.tv_usec = 0;
+        if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0) {
+            LOG(log_error, logtype_cnid, "getfd: set SO_SNDTIMEO %s: %s", host, strerror(errno));
+            close(sock);
+            continue;
+        }
+        
+        if (connect(sock, p->ai_addr, p->ai_addrlen) == -1) {
+            err = errno;
+            close(sock);
+            sock=-1;
+            LOG(log_error, logtype_cnid, "getfd: connect %s: %s", host, strerror(err));
+            continue;
+        }
+        
+        /* We've got a socket */
+        break;
     }
 
-    tv.tv_sec = SOCK_DELAY;
-    tv.tv_usec = 0;
-    if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0) {
-        LOG(log_error, logtype_cnid, "getfd: set SO_SNDTIMEO %s: %s", host, strerror(errno));
-        close(sock);
-        return(-1);
-    }
+exit:
+    freeaddrinfo(servinfo);
 
-    if(connect(sock ,(struct sockaddr*)&server,sizeof(server))==-1) {
-        err = errno;
-        close(sock);
-        sock=-1;
-        LOG(log_error, logtype_cnid, "getfd: connect %s: %s", host, strerror(err));
+    if (p == NULL) {
         switch (err) {
         case ENETUNREACH:
         case ECONNREFUSED:
             delay(5);
-            break;
+            return -1;
         }
+        LOG(log_error, logtype_cnid, "tsock_getfd: no suitable network config from %s:%s", host, port);
+        return -1;
     }
 
-    LOG(log_debug7, logtype_cnid, "tsock_getfd: using sockfd %d for cnid server '%s:%d'", sock, host, port);
-
     return(sock);
 }
 
@@ -189,7 +192,7 @@ static int init_tsock(CNID_private *db)
     int len;
     struct iovec iov[2];
 
-    LOG(log_debug, logtype_cnid, "init_tsock: BEGIN. Opening volume '%s'", db->db_dir);
+    LOG(log_debug, logtype_cnid, "init_tsock: BEGIN. Opening volume '%s', CNID Server: %s/%s", db->db_dir, Cnid_srv, Cnid_port);
 
     if ((fd = tsock_getfd(Cnid_srv, Cnid_port)) < 0)
         return -1;
index 5ac8dec74f7ba1048744125f2d7f033882553cb2..547eed997ff815c6379c3423a60a22d2e62a43a3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: dsi_init.c,v 1.9 2009-10-25 06:13:11 didg Exp $
+ * $Id: dsi_init.c,v 1.10 2009-11-05 14:38:08 franklahm Exp $
  *
  * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu)
  * All rights reserved. See COPYRIGHT.
@@ -17,7 +17,7 @@
 
 DSI *dsi_init(const dsi_proto protocol, const char *program, 
              const char *hostname, const char *address,
-             const int port, const int proxy, const u_int32_t quantum)
+             const char *port, const int proxy, const u_int32_t quantum)
 {
     DSI                *dsi;
 
index ac16cb682035d5a13390e9443e63467eb151c21c..8872f8f3cf8b4a5f09972cc764c37974f063a0e7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: dsi_private.h,v 1.3 2009-10-13 22:55:37 didg Exp $
+ * $Id: dsi_private.h,v 1.4 2009-11-05 14:38:08 franklahm Exp $
  *
  * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu)
  * All rights reserved. See COPYRIGHT.
@@ -19,7 +19,7 @@
 
 extern int dsi_tcp_init (DSI *, const char * /*host*/, 
                             const char * /*address*/,
-                            const u_int16_t /*port*/,
+                            const char * /*port*/,
                             const int /*proxy*/);
 
 #endif /* _DSI_PRIVATE_H */
index ae2cf2bfc888b7c6f0ad65ef0ce246ef2c3dd370..9fcf6146cce20408e961df0b20cc8d6470d119a6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: dsi_tcp.c,v 1.17 2009-11-02 10:27:13 franklahm Exp $
+ * $Id: dsi_tcp.c,v 1.18 2009-11-05 14:38:08 franklahm Exp $
  *
  * Copyright (c) 1997, 1998 Adrian Sun (asun@zoology.washington.edu)
  * All rights reserved. See COPYRIGHT.
@@ -120,8 +120,7 @@ static int dsi_tcp_open(DSI *dsi)
     SOCKLEN_T len;
 
     len = sizeof(dsi->client);
-    dsi->socket = accept(dsi->serversock, (struct sockaddr *) &dsi->client,
-                         &len);
+    dsi->socket = accept(dsi->serversock, (struct sockaddr *) &dsi->client, &len);
 
 #ifdef TCPWRAP
     {
@@ -226,10 +225,9 @@ static int dsi_tcp_open(DSI *dsi)
 
         dsi_tcp_timeout(dsi);
 
-        LOG(log_info, logtype_default,"ASIP session:%u(%d) from %s:%u(%d)",
-            ntohs(dsi->server.sin_port), dsi->serversock,
-            inet_ntoa(dsi->client.sin_addr), ntohs(dsi->client.sin_port),
-            dsi->socket);
+        LOG(log_info, logtype_default, "AFP/TCP session from %s:%u",
+            getip_string((struct sockaddr *)&dsi->client),
+            getip_port((struct sockaddr *)&dsi->client));
     }
 
     /* send back our pid */
@@ -238,134 +236,173 @@ static int dsi_tcp_open(DSI *dsi)
 
 /* this needs to accept passed in addresses */
 int dsi_tcp_init(DSI *dsi, const char *hostname, const char *address,
-                 const u_int16_t ipport, const int proxy)
+                 const char *port, const int proxy)
 {
-    struct servent     *service;
-    struct hostent     *host;
-    int                port;
+    int                ret;
+    int                flag;
+    struct addrinfo    hints, *servinfo, *p;
 
     dsi->protocol = DSI_TCPIP;
 
-    /* create a socket */
-    if (proxy)
-        dsi->serversock = -1;
-    else if ((dsi->serversock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
-        return 0;
-
-    /* find port */
-    if (ipport)
-        port = htons(ipport);
-    else if ((service = getservbyname("afpovertcp", "tcp")))
-        port = service->s_port;
+    /* Prepare hint for getaddrinfo */
+    memset(&hints, 0, sizeof hints);
+    hints.ai_family = AF_UNSPEC;
+    hints.ai_socktype = SOCK_STREAM;
+    hints.ai_flags = AI_NUMERICSERV;
+    if ( ! address)
+        hints.ai_flags |= AI_PASSIVE;
     else
-        port = htons(DSI_AFPOVERTCP_PORT);
+        hints.ai_flags |= AI_NUMERICHOST;
 
-    /* find address */
-    if (!address)
-        dsi->server.sin_addr.s_addr = htonl(INADDR_ANY);
-    else if (inet_aton(address, &dsi->server.sin_addr) == 0) {
-        LOG(log_info, logtype_default, "dsi_tcp: invalid address (%s)", address);
+    if ((ret = getaddrinfo(address ? address : NULL, port ? port : "548", &hints, &servinfo)) != 0) {
+        LOG(log_error, logtype_default, "dsi_tcp_init: getaddrinfo: %s\n", gai_strerror(ret));
         return 0;
     }
 
-    dsi->server.sin_family = AF_INET;
-    dsi->server.sin_port = port;
+    /* create a socket */
+    if (proxy)
+        dsi->serversock = -1;
+    else {
+        /* loop through all the results and bind to the first we can */
+        for (p = servinfo; p != NULL; p = p->ai_next) {
+            if ((dsi->serversock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
+                LOG(log_info, logtype_default, "dsi_tcp_init: socket: %s", strerror(errno));
+                continue;
+            }
 
-    if (!proxy) {
-        /* this deals w/ quick close/opens */
+            /*
+             * Set some socket options:
+             * SO_REUSEADDR deals w/ quick close/opens
+             * TCP_NODELAY diables Nagle
+             */
 #ifdef SO_REUSEADDR
-        port = 1;
-        setsockopt(dsi->serversock, SOL_SOCKET, SO_REUSEADDR, &port, sizeof(port));
+            flag = 1;
+            setsockopt(dsi->serversock, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag));
 #endif
 
 #ifdef USE_TCP_NODELAY
-
 #ifndef SOL_TCP
 #define SOL_TCP IPPROTO_TCP
 #endif
-
-        port = 1;
-        setsockopt(dsi->serversock, SOL_TCP, TCP_NODELAY, &port, sizeof(port));
+            flag = 1;
+            setsockopt(dsi->serversock, SOL_TCP, TCP_NODELAY, &flag, sizeof(flag));
 #endif /* USE_TCP_NODELAY */
+            
+            if (bind(dsi->serversock, p->ai_addr, p->ai_addrlen) == -1) {
+                close(dsi->serversock);
+                LOG(log_info, logtype_default, "dsi_tcp_init: bind: %s\n", strerror(errno));
+                continue;
+            }
+
+            if (listen(dsi->serversock, DSI_TCPMAXPEND) < 0) {
+                close(dsi->serversock);
+                LOG(log_info, logtype_default, "dsi_tcp_init: listen: %s\n", strerror(errno));
+                continue;
+            }
+            
+            break;
+        }
 
-        /* now, bind the socket and set it up for listening */
-        if ((bind(dsi->serversock, (struct sockaddr *) &dsi->server,
-                  sizeof(dsi->server)) < 0) ||
-            (listen(dsi->serversock, DSI_TCPMAXPEND) < 0)) {
-            close(dsi->serversock);
+        if (p == NULL)  {
+            LOG(log_error, logtype_default, "dsi_tcp_init: no suitable network config for TCP socket");
+            freeaddrinfo(servinfo);
             return 0;
         }
-    }
+
+        /* Copy struct sockaddr to struct sockaddr_storage */
+        memcpy(&dsi->server, p->ai_addr, p->ai_addrlen);
+        freeaddrinfo(servinfo);
+    } /* if (proxy) */
 
     /* Point protocol specific functions to tcp versions */
     dsi->proto_open = dsi_tcp_open;
     dsi->proto_close = dsi_tcp_close;
 
-    /* get real address for GetStatus. we'll go through the list of
-     * interfaces if necessary. */
+    /* get real address for GetStatus. */
 
     if (address) {
         /* address is a parameter, use it 'as is' */
         return 1;
     }
 
-    if (!(host = gethostbyname(hostname)) ) { /* we can't resolve the name */
+    /* Prepare hint for getaddrinfo */
+    memset(&hints, 0, sizeof hints);
+    hints.ai_family = AF_UNSPEC;
+    hints.ai_socktype = SOCK_STREAM;
 
-        LOG(log_info, logtype_default, "dsi_tcp: cannot resolve hostname '%s'", hostname);
-        if (proxy) {
-            /* give up we have nothing to advertise */
-            return 0;
-        }
+    if ((ret = getaddrinfo(hostname, port ? port : "548", &hints, &servinfo)) != 0) {
+        LOG(log_error, logtype_default, "dsi_tcp_init: getaddrinfo: %s\n", gai_strerror(ret));
+        return 0;
     }
-    else {
-        if (( ((struct in_addr *) host->h_addr)->s_addr & htonl(0x7F000000) ) !=  htonl(0x7F000000)) { /* FIXME ugly check */
-            dsi->server.sin_addr.s_addr = ((struct in_addr *) host->h_addr)->s_addr;
-            return 1;
+
+    for (p = servinfo; p != NULL; p = p->ai_next) {
+        if (p->ai_family == AF_INET) { // IPv4
+            struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr;
+            if ( (ipv4->sin_addr.s_addr & htonl(0x7f000000)) != htonl(0x7f000000) )
+                break;
+        } else { // IPv6
+            struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
+            unsigned char ipv6loopb[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
+            if ((memcmp(ipv6->sin6_addr.s6_addr, ipv6loopb, 16)) != 0)
+                break;
         }
-        LOG(log_info, logtype_default, "dsi_tcp: hostname '%s' resolves to loopback address", hostname);
     }
-    {
-        char **start, **list;
-        struct ifreq ifr;
 
-        /* get it from the interface list */
-        start = list = getifacelist();
-        while (list && *list) {
-            strlcpy(ifr.ifr_name, *list, sizeof(ifr.ifr_name));
-            list++;
+    if (p == NULL) { /* no advertisable address found */
+        LOG(log_info, logtype_default, "dsi_tcp: cannot resolve hostname '%s'", hostname);
+        freeaddrinfo(servinfo);
+        return 0;
+    }
+
+    /* Store found address in dsi->server */
+    memcpy(&dsi->server, p->ai_addr, p->ai_addrlen);
+    freeaddrinfo(servinfo);
+    return 1;
+
+    /*
+     * Note: I'll leave this code just in case. With getaddrinfo I guess we
+     * should be able to get an IP != 127.0.0.1 or ::1 from the hostname. Hopefully.
+     */
+#if 0
+    /* get it from the interface list */
+    char **start, **list;
+    struct ifreq ifr;
+    start = list = getifacelist();
+    while (list && *list) {
+        strlcpy(ifr.ifr_name, *list, sizeof(ifr.ifr_name));
+        list++;
 
 #ifndef IFF_SLAVE
 #define IFF_SLAVE 0
 #endif
 
-            if (ioctl(dsi->serversock, SIOCGIFFLAGS, &ifr) < 0)
-                continue;
-
-            if (ifr.ifr_flags & (IFF_LOOPBACK | IFF_POINTOPOINT | IFF_SLAVE))
-                continue;
+        if (ioctl(dsi->serversock, SIOCGIFFLAGS, &ifr) < 0)
+            continue;
 
-            if (!(ifr.ifr_flags & (IFF_UP | IFF_RUNNING)) )
-                continue;
+        if (ifr.ifr_flags & (IFF_LOOPBACK | IFF_POINTOPOINT | IFF_SLAVE))
+            continue;
 
-            if (ioctl(dsi->serversock, SIOCGIFADDR, &ifr) < 0)
-                continue;
+        if (!(ifr.ifr_flags & (IFF_UP | IFF_RUNNING)) )
+            continue;
 
-            dsi->server.sin_addr.s_addr =
-                ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr;
-            LOG(log_info, logtype_default, "dsi_tcp: '%s' on interface '%s' will be used instead.",
-                inet_ntoa(dsi->server.sin_addr), ifr.ifr_name);
-            goto iflist_done;
-        }
-        LOG(log_info, logtype_default, "dsi_tcp (Chooser will not select afp/tcp) \
-Check to make sure %s is in /etc/hosts and the correct domain is in \
-/etc/resolv.conf: %s", hostname, strerror(errno));
+        if (ioctl(dsi->serversock, SIOCGIFADDR, &ifr) < 0)
+            continue;
 
-    iflist_done:
-        if (start)
-            freeifacelist(start);
+        dsi->server.sin_addr.s_addr =
+            ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr;
+        LOG(log_info, logtype_default, "dsi_tcp: '%s' on interface '%s' will be used instead.",
+            inet_ntoa(dsi->server.sin_addr), ifr.ifr_name);
+        goto iflist_done;
     }
+    LOG(log_info, logtype_default, "dsi_tcp (Chooser will not select afp/tcp) "
+        "Check to make sure %s is in /etc/hosts and the correct domain is in "
+        "/etc/resolv.conf: %s", hostname, strerror(errno));
 
+iflist_done:
+    if (start)
+        freeifacelist(start);
     return 1;
 
+#endif
 }
 
index 5843d1d632a1b923af5efd4bae0a295fa4400ea7..8b4e6e7f434098e5c3b6841ea3598abd782730ff 100644 (file)
@@ -1,5 +1,5 @@
 /*
-   $Id: socket.c,v 1.1 2009-10-26 12:35:56 franklahm Exp $
+   $Id: socket.c,v 1.2 2009-11-05 14:38:08 franklahm Exp $
    Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
 
    This program is free software; you can redistribute it and/or modify
 
 #include <unistd.h>
 #include <fcntl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <string.h>
+
+#include <atalk/logger.h>
+
+static char ipv4mapprefix[] = {0,0,0,0,0,0,0,0,0,0,0xff,0xff};
 
 int setnonblock(int fd, int cmd)
 {
@@ -39,3 +47,105 @@ int setnonblock(int fd, int cmd)
 
     return 0;
 }
+
+const char *getip_string(const struct sockaddr *sa)
+{
+    static char ip4[INET_ADDRSTRLEN];
+    static char ip6[INET6_ADDRSTRLEN];
+
+    switch (sa->sa_family) {
+
+    case AF_INET: {
+        const struct sockaddr_in *sai4 = (const struct sockaddr_in *)sa;
+        if ((inet_ntop(AF_INET, &(sai4->sin_addr), ip4, INET_ADDRSTRLEN)) == NULL)
+            return "0.0.0.0";
+        return ip4;
+    }
+    case AF_INET6: {
+        const struct sockaddr_in6 *sai6 = (const struct sockaddr_in6 *)sa;
+        if ((inet_ntop(AF_INET6, &(sai6->sin6_addr), ip6, INET6_ADDRSTRLEN)) == NULL)
+            return "::0";
+
+        /* Deal with IPv6 mapped IPv4 addresses*/
+        if ((memcmp(sai6->sin6_addr.s6_addr, ipv4mapprefix, sizeof(ipv4mapprefix))) == 0)
+            return (strrchr(ip6, ':') + 1);
+        return ip6;
+    }
+    default:
+        return "getip_string ERROR";
+    }
+
+    /* We never get here */
+}
+
+unsigned int getip_port(const struct sockaddr  *sa)
+{
+    if (sa->sa_family == AF_INET) { /* IPv4 */
+        const struct sockaddr_in *sai4 = (const struct sockaddr_in *)sa;
+        return ntohs(sai4->sin_port);
+    } else {                       /* IPv6 */
+        const struct sockaddr_in6 *sai6 = (const struct sockaddr_in6 *)sa;
+        return ntohs(sai6->sin6_port);
+    }
+
+    /* We never get here */
+}
+
+void apply_ip_mask(struct sockaddr *sa, uint32_t mask)
+{
+    if (mask < 0)
+        return;
+
+    switch (sa->sa_family) {
+    case AF_INET: {
+        if (mask >= 32)
+            return;
+
+        struct sockaddr_in *si = (struct sockaddr_in *)sa;
+        uint32_t nmask = mask ? ~((1 << (32 - mask)) - 1) : 0;
+        si->sin_addr.s_addr &= htonl(nmask);
+        break;
+    }
+    case AF_INET6: {
+        if (mask >= 128)
+            return;
+
+        int i, maskbytes, maskbits;
+        struct sockaddr_in6 *si6 = (struct sockaddr_in6 *)sa;
+
+        /* Deal with IPv6 mapped IPv4 addresses*/
+        if ((memcmp(si6->sin6_addr.s6_addr, ipv4mapprefix, sizeof(ipv4mapprefix))) == 0) {
+            mask += 96;
+            if (mask >= 128)
+                return;
+        }
+
+        maskbytes = (128 - mask) / 8; /* maskbytes really are those that will be 0'ed */
+        maskbits = mask % 8;
+
+        for (i = maskbytes - 1; i >= 0; i--)
+            si6->sin6_addr.s6_addr[15 - i] = 0;
+        if (maskbits)
+            si6->sin6_addr.s6_addr[15 - maskbytes] &= ~((1 << (8 - maskbits)) - 1);
+        break;
+    }
+    default:
+        break;
+    }
+}
+
+int compare_ip(const struct sockaddr *sa1, const struct sockaddr *sa2)
+{
+    int ret;
+    const char *ip1;
+    const char *ip2;
+
+    ip1 = strdup(getip_string(sa1));
+    ip2 = getip_string(sa2);
+
+    ret = strcmp(ip1, ip2);
+
+    free(ip1);
+
+    return ret;
+}