Hi,
>>> Fri, 15 Oct 2004 22:20:58 +0900,
>>> Hajimu UMEMOTO <ume@...> said:
ume> I cannot test it for now. So, I'll test it later.
I've just tested it, and found a problem. The retern code of
local_addr() was opposite.
Here is a patch against plain 1.5.10. It seems working here.
Please throw my previous patch away, and try this one instead.
Index: sync.c
diff -u -p sync.c.orig sync.c
--- sync.c.orig Tue Aug 10 05:26:52 2004
+++ sync.c Fri Oct 15 22:09:18 2004
@@ -72,6 +72,7 @@ pthread_rwlock_t sync_lock; /* For all p
pthread_cond_t sync_sleepflag;
static void sync_listen(char *, char *, struct sync_master_sock *);
+static int local_addr(const struct sockaddr *sa, const socklen_t salen);
void
peer_init(void) {
@@ -144,6 +145,7 @@ peer_add(peername)
peer->p_qlen = 0;
peer->p_stream = NULL;
+ peer->p_flags = 0;
TAILQ_INIT(&peer->p_deferred);
PEER_WRLOCK;
@@ -313,6 +315,21 @@ peer_connect(peer) /* peer list is read-
peer->p_name, gai_strerror(err), peer->p_qlen);
return -1;
}
+
+ for (res = res0; res; res = res->ai_next) {
+ /*We only test an address family which kernel supports. */
+ s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+ if (s == -1)
+ continue;
+ close(s);
+
+ if (local_addr(res->ai_addr, res->ai_addrlen)) {
+ peer->p_flags |= P_LOCAL;
+ freeaddrinfo(res0);
+ return -1;
+ }
+ }
+
for (res = res0; res; res = res->ai_next) {
s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (s == -1)
@@ -358,6 +375,12 @@ peer_connect(peer) /* peer list is read-
syslog(LOG_ERR, "cannot sync, invalid address");
return -1;
}
+
+ if (local_addr(SA(&raddr), raddrlen)) {
+ peer->flags |= P_LOCAL;
+ return -1;
+ }
+
switch (SA(&raddr)->sa_family) {
case AF_INET:
SA4(&raddr)->sin_port = service;
@@ -1085,6 +1108,10 @@ sync_sender(dontcare)
goto out;
LIST_FOREACH(peer, &peer_head, p_list) {
+ /* Don't try to sync with ourselves */
+ if (peer->p_flags & P_LOCAL)
+ continue;
+
/* XXX take a read lock and then upgrade it */
while (TAILQ_EMPTY(&peer->p_deferred) == 0) {
SYNC_WRLOCK;
@@ -1125,4 +1152,55 @@ out:
tv3.tv_sec, tv3.tv_usec);
}
}
+}
+
+
+static int
+local_addr(sa, salen)
+ const struct sockaddr *sa;
+ const socklen_t salen;
+{
+ sockaddr_t addr;
+ int sfd, islocal;
+
+ memcpy(&addr, sa, salen);
+ switch(sa->sa_family) {
+ case AF_INET:
+ SA4(&addr)->sin_port = 0;
+ break;
+
+#ifdef AF_INET6
+ case AF_INET6:
+ SA6(&addr)->sin6_port = 0;
+ break;
+#endif
+
+ default:
+ syslog(LOG_ERR, "local_addr: unsupported AF %d\n",
+ sa->sa_family);
+ return -1;
+ break;
+ }
+
+ if ((sfd = socket(sa->sa_family, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
+ syslog(LOG_ERR, "local_addr: socket failed: %s\n",
+ strerror(errno));
+ return -1;
+ }
+
+ if (bind(sfd, sa, salen) == -1) {
+ if (errno != EADDRNOTAVAIL) {
+ syslog(LOG_ERR, "local_addr: bind failed: %s\n",
+ strerror(errno));
+ islocal = -1;
+ } else {
+ islocal = 0;
+ }
+ } else {
+ islocal = 1;
+ }
+
+ close(sfd);
+
+ return islocal;
}
Index: sync.h
diff -u sync.h.orig sync.h
--- sync.h.orig Mon Aug 9 06:24:20 2004
+++ sync.h Fri Oct 15 20:07:36 2004
@@ -67,7 +67,10 @@
struct synclist p_deferred;
LIST_ENTRY(peer) p_list;
size_t p_qlen;
+ int p_flags;
};
+
+#define P_LOCAL 1
typedef enum { PS_CREATE, PS_DELETE } peer_sync_t;
--
Hajimu UMEMOTO @ Internet Mutual Aid Society Yokohama, Japan
ume@... ume@{,jp.}FreeBSD.org
http://www.imasy.org/~ume/