/*
- * $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.
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,
}
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
/*
- * $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.
#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
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))
/* 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)))
options->transports &= ~AFPTRANS_DDP;
break;
case 'S':
- options->port = atoi(optarg);
+ options->port = optarg;
break;
case 'T':
options->transports &= ~AFPTRANS_TCP;
/*
- * $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.
};
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;
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 *);
/*
- * $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.
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)))
/* 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;
+ }
+
}
}
DSI *dsi;
char *status = NULL;
size_t statuslen;
- int c, sigoff;
+ int c, sigoff, ipok;
if (!(aspconfig || dsiconfig) || !options)
return;
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;
* (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);
/*
- * $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.
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)
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
/*
- * $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.
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;
} 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);
} 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;
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;
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;
}
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
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)
/*
- * $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>
* to reconnect every 5 secondes, catch it */
#define MAXVOLS 512
#define DEFAULTHOST "localhost"
-#define DEFAULTPORT 4700
+#define DEFAULTPORT "4700"
struct server {
char *name;
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;
}
break;
case 'p':
- port = atoi(optarg);
+ port = strdup(optarg);
break;
case 's':
dbdpn = strdup(optarg);
/*
- * $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.
}
/* ---------------
- 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;
}
/*
- * $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.
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
/*
- * $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)
{
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;
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;
/*
- * $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)
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;
/*
- * $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)
#include <sia.h>
#include <siad.h>
-static char *clientname;
+static const char *clientname;
#endif /* TRU64 */
/* dhx passwd */
/*
- * $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)
* 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;
/*
- * $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)
#include <sia.h>
#include <siad.h>
-static char *clientname;
+static const char *clientname;
#endif /* TRU64 */
/*XXX in etc/papd/file.h */
typedef struct DSI {
dsi_proto protocol;
struct dsi_block header;
- struct sockaddr_in server, client;
+ struct sockaddr_storage server, client;
struct itimerval timer;
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);
/*
- * $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
* 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);
/*
- * $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.
}
/* ----------- */
-extern char Cnid_srv[MAXHOSTNAMELEN + 1];
-extern int Cnid_port;
+extern char *Cnid_srv;
+extern char *Cnid_port;
#define MAX_DELAY 40
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);
}
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;
/*
- * $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.
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;
/*
- * $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.
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 */
/*
- * $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.
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
{
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 */
/* 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
}
/*
- $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)
{
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;
+}