]> git.pld-linux.org Git - packages/autofs.git/blob - autofs-5.0.4-ipv6-name-and-address-support.patch
- import latest patchset.
[packages/autofs.git] / autofs-5.0.4-ipv6-name-and-address-support.patch
1 autofs-5.0.4 - ipv6 name and address support
2
3 From: Ian Kent <raven@themaw.net>
4
5 For ipv6 we need to convert all ipv4 specific function calls to ipv6
6 compatible function calls and update the rpc code to deal with ipv6
7 addresses. The host proximity calculation also needes to be updated.
8
9 I'm sure this isn't completely correct yet and it will need more work
10 as I become more familiar with how ipv6 and subneting with it is used.
11 The changes so far function correctly for the current autofs
12 connectathon test suite maps so I hope there aren't any regressions
13 with current map configurations.
14 ---
15
16  include/replicated.h |    2 
17  include/rpc_subs.h   |    4 
18  lib/rpc_subs.c       |  484 ++++++++++++++++++++++++++++++++------------------
19  modules/cyrus-sasl.c |   17 +-
20  modules/replicated.c |  235 +++++++++++++++++-------
21  5 files changed, 499 insertions(+), 243 deletions(-)
22
23
24 diff --git a/include/replicated.h b/include/replicated.h
25 index 88cd08a..e0133ff 100644
26 --- a/include/replicated.h
27 +++ b/include/replicated.h
28 @@ -51,7 +51,7 @@
29  
30  struct host {
31         char *name;
32 -       char *addr;
33 +       struct sockaddr *addr;
34         size_t addr_len;
35         char *path;
36         unsigned int version;
37 diff --git a/include/rpc_subs.h b/include/rpc_subs.h
38 index e20a89d..87fd568 100644
39 --- a/include/rpc_subs.h
40 +++ b/include/rpc_subs.h
41 @@ -46,7 +46,7 @@
42  
43  struct conn_info {
44         const char *host;
45 -       const char *addr;
46 +       struct sockaddr *addr;
47         size_t addr_len;
48         unsigned short port;
49         unsigned long program;
50 @@ -63,7 +63,7 @@ int rpc_udp_getclient(struct conn_info *, unsigned int, unsigned int);
51  void rpc_destroy_udp_client(struct conn_info *);
52  int rpc_tcp_getclient(struct conn_info *, unsigned int, unsigned int);
53  void rpc_destroy_tcp_client(struct conn_info *);
54 -int rpc_portmap_getclient(struct conn_info *, const char *, const char *, size_t, const char *, unsigned int);
55 +int rpc_portmap_getclient(struct conn_info *, const char *, struct sockaddr *, size_t, const char *, unsigned int);
56  unsigned short rpc_portmap_getport(struct conn_info *, struct pmap *);
57  int rpc_ping_proto(struct conn_info *);
58  int rpc_ping(const char *, long, long, unsigned int);
59 diff --git a/lib/rpc_subs.c b/lib/rpc_subs.c
60 index 7b347a7..a822f1f 100644
61 --- a/lib/rpc_subs.c
62 +++ b/lib/rpc_subs.c
63 @@ -17,10 +17,11 @@
64  #define _GNU_SOURCE
65  #endif
66  
67 +#include "config.h"
68 +
69  #include <rpc/types.h>
70  #include <rpc/rpc.h>
71  #include <rpc/pmap_prot.h>
72 -
73  #include <sys/socket.h>
74  #include <netdb.h>
75  #include <net/if.h>
76 @@ -54,145 +55,76 @@
77  
78  inline void dump_core(void);
79  
80 -/*
81 - * Create a UDP RPC client
82 - */
83 -static CLIENT *create_udp_client(struct conn_info *info)
84 +static CLIENT *rpc_clntudp_create(struct sockaddr *addr, struct conn_info *info, int *fd)
85  {
86 -       int fd, ret, ghn_errno;
87 -       CLIENT *client;
88 -       struct sockaddr_in laddr, raddr;
89 -       struct hostent hp;
90 -       struct hostent *php = &hp;
91 -       struct hostent *result;
92 -       char buf[HOST_ENT_BUF_SIZE];
93 -       size_t len;
94 -
95 -       if (info->proto->p_proto != IPPROTO_UDP)
96 -               return NULL;
97 -
98 -       if (info->client) {
99 -               if (!clnt_control(info->client, CLGET_FD, (char *) &fd)) {
100 -                       fd = -1;
101 -                       clnt_destroy(info->client);
102 -                       info->client = NULL;
103 -               } else {
104 -                       clnt_control(info->client, CLSET_FD_NCLOSE, NULL);
105 -                       clnt_destroy(info->client);
106 -               }
107 -       }
108 -
109 -       memset(&laddr, 0, sizeof(laddr));
110 -       memset(&raddr, 0, sizeof(raddr));
111 -
112 -       raddr.sin_family = AF_INET;
113 -       if (info->addr) {
114 -               memcpy(&raddr.sin_addr.s_addr, info->addr, info->addr_len);
115 -               goto got_addr;
116 -       }
117 -
118 -       if (inet_aton(info->host, &raddr.sin_addr))
119 -               goto got_addr;
120 -
121 -       memset(&hp, 0, sizeof(struct hostent));
122 -
123 -       ret = gethostbyname_r(info->host, php,
124 -                       buf, HOST_ENT_BUF_SIZE, &result, &ghn_errno);
125 -       if (ret || !result) {
126 -               int err = ghn_errno == -1 ? errno : ghn_errno;
127 -               char *estr = strerror_r(err, buf, HOST_ENT_BUF_SIZE);
128 -               logerr("hostname lookup failed: %s", estr);
129 -               goto out_close;
130 -       }
131 -       memcpy(&raddr.sin_addr.s_addr, php->h_addr, php->h_length);
132 -
133 -got_addr:
134 -       raddr.sin_port = htons(info->port);
135 -
136 -       if (!info->client) {
137 -               /*
138 -                * bind to any unused port.  If we left this up to the rpc
139 -                * layer, it would bind to a reserved port, which has been shown
140 -                * to exhaust the reserved port range in some situations.
141 -                */
142 -               fd = open_sock(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
143 -               if (fd < 0)
144 -                       return NULL;
145 -
146 -               laddr.sin_family = AF_INET;
147 -               laddr.sin_port = 0;
148 -               laddr.sin_addr.s_addr = htonl(INADDR_ANY);
149 -
150 -               len = sizeof(struct sockaddr_in);
151 -               if (bind(fd, (struct sockaddr *)&laddr, len) < 0) {
152 -                       close(fd);
153 -                       fd = RPC_ANYSOCK;
154 -                       /* FALLTHROUGH */
155 -               }
156 -       }
157 -
158 -       client = clntudp_bufcreate(&raddr,
159 -                                  info->program, info->version,
160 -                                  info->timeout, &fd,
161 -                                  info->send_sz, info->recv_sz);
162 +       struct sockaddr_in *in4_raddr;
163 +       struct sockaddr_in6 *in6_raddr;
164 +       CLIENT *client = NULL;
165 +
166 +       switch (addr->sa_family) {
167 +       case AF_INET:
168 +               in4_raddr = (struct sockaddr_in *) addr;
169 +               in4_raddr->sin_port = htons(info->port);
170 +               client = clntudp_bufcreate(in4_raddr,
171 +                                          info->program, info->version,
172 +                                          info->timeout, fd,
173 +                                          info->send_sz, info->recv_sz);
174 +               break;
175  
176 -       if (!client) {
177 -               info->client = NULL;
178 -               goto out_close;
179 -       }
180 +       case AF_INET6:
181 +#ifndef INET6
182 +               /* Quiet compile warning */
183 +               in6_raddr = NULL;
184 +#else
185 +               in6_raddr = (struct sockaddr_in6 *) addr;
186 +               in6_raddr->sin6_port = htons(info->port);
187 +               client = clntudp6_bufcreate(in6_raddr,
188 +                                           info->program, info->version,
189 +                                           info->timeout, fd,
190 +                                           info->send_sz, info->recv_sz);
191 +#endif
192 +               break;
193  
194 -       /* Close socket fd on destroy, as is default for rpcowned fds */
195 -       if  (!clnt_control(client, CLSET_FD_CLOSE, NULL)) {
196 -               clnt_destroy(client);
197 -               info->client = NULL;
198 -               goto out_close;
199 +       default:
200 +               break;
201         }
202  
203         return client;
204 -
205 -out_close:
206 -       if (fd != -1)
207 -               close(fd);
208 -       return NULL;
209  }
210  
211 -int rpc_udp_getclient(struct conn_info *info,
212 -                     unsigned int program, unsigned int version)
213 +static CLIENT *rpc_clnttcp_create(struct sockaddr *addr, struct conn_info *info, int *fd)
214  {
215 -       struct protoent *pe_proto;
216 -       CLIENT *client;
217 +       struct sockaddr_in *in4_raddr;
218 +       struct sockaddr_in6 *in6_raddr;
219 +       CLIENT *client = NULL;
220 +
221 +       switch (addr->sa_family) {
222 +       case AF_INET:
223 +               in4_raddr = (struct sockaddr_in *) addr;
224 +               in4_raddr->sin_port = htons(info->port);
225 +               client = clnttcp_create(in4_raddr,
226 +                                       info->program, info->version, fd,
227 +                                       info->send_sz, info->recv_sz);
228 +               break;
229  
230 -       if (!info->client) {
231 -               pe_proto = getprotobyname("udp");
232 -               if (!pe_proto)
233 -                       return 0;
234 +       case AF_INET6:
235 +#ifndef INET6
236 +               /* Quiet compile warning */
237 +               in6_raddr = NULL;
238 +#else
239 +               in6_raddr = (struct sockaddr_in6 *) addr;
240 +               in6_raddr->sin6_port = htons(info->port);
241 +               client = clnttcp6_create(in6_raddr,
242 +                                        info->program, info->version, fd,
243 +                                        info->send_sz, info->recv_sz);
244 +#endif
245 +               break;
246  
247 -               info->proto = pe_proto;
248 -               info->send_sz = UDPMSGSIZE;
249 -               info->recv_sz = UDPMSGSIZE;
250 +       default:
251 +               break;
252         }
253  
254 -       info->program = program;
255 -       info->version = version;
256 -
257 -       client = create_udp_client(info);
258 -
259 -       if (!client)
260 -               return 0;
261 -
262 -       info->client = client;
263 -
264 -       return 1;
265 -}
266 -
267 -void rpc_destroy_udp_client(struct conn_info *info)
268 -{
269 -       if (!info->client)
270 -               return;
271 -
272 -       clnt_destroy(info->client);
273 -       info->client = NULL;
274 -       return;
275 +       return client;
276  }
277  
278  /*
279 @@ -201,12 +133,11 @@ void rpc_destroy_udp_client(struct conn_info *info)
280   *  The input struct timeval always has tv_nsec set to zero,
281   *  we only ever use tv_sec for timeouts.
282   */
283 -static int connect_nb(int fd, struct sockaddr_in *addr, struct timeval *tout)
284 +static int connect_nb(int fd, struct sockaddr *addr, socklen_t len, struct timeval *tout)
285  {
286         struct pollfd pfd[1];
287         int timeout = tout->tv_sec;
288         int flags, ret;
289 -       socklen_t len;
290  
291         flags = fcntl(fd, F_GETFL, 0);
292         if (flags < 0)
293 @@ -221,8 +152,7 @@ static int connect_nb(int fd, struct sockaddr_in *addr, struct timeval *tout)
294          * we set ret = -errno to capture it in case we decide to
295          * use it later.
296          */
297 -       len = sizeof(struct sockaddr);
298 -       ret = connect(fd, (struct sockaddr *)addr, len);
299 +       ret = connect(fd, addr, len);
300         if (ret < 0 && errno != EINPROGRESS) {
301                 ret = -errno;
302                 goto done;
303 @@ -277,26 +207,241 @@ done:
304         return ret;
305  }
306  
307 +static CLIENT *rpc_do_create_client(struct sockaddr *addr, struct conn_info *info, int *fd)
308 +{
309 +       CLIENT *client = NULL;
310 +       struct sockaddr *laddr;
311 +       struct sockaddr_in in4_laddr;
312 +       struct sockaddr_in6 in6_laddr;
313 +       int type, proto;
314 +       socklen_t slen;
315 +
316 +       proto = info->proto->p_proto;
317 +       if (proto == IPPROTO_UDP)
318 +               type = SOCK_DGRAM;
319 +       else
320 +               type = SOCK_STREAM;
321 +
322 +       /*
323 +        * bind to any unused port.  If we left this up to the rpc
324 +        * layer, it would bind to a reserved port, which has been shown
325 +        * to exhaust the reserved port range in some situations.
326 +        */
327 +       switch (addr->sa_family) {
328 +       case AF_INET:
329 +               in4_laddr.sin_family = AF_INET;
330 +               in4_laddr.sin_port = htons(0);
331 +               in4_laddr.sin_addr.s_addr = htonl(INADDR_ANY);
332 +               slen = sizeof(struct sockaddr_in);
333 +               laddr = (struct sockaddr *) &in4_laddr;
334 +               break;
335 +
336 +       case AF_INET6:
337 +#ifndef INET6
338 +               /* Quiet compiler */
339 +               in6_laddr.sin6_family = AF_INET6;
340 +               return NULL;
341 +#else
342 +               in6_laddr.sin6_family = AF_INET6;
343 +               in6_laddr.sin6_port = htons(0);
344 +               in6_laddr.sin6_addr = in6addr_any;
345 +               slen = sizeof(struct sockaddr_in6);
346 +               laddr = (struct sockaddr *) &in6_laddr;
347 +               break;
348 +#endif
349 +       default:
350 +               return NULL;
351 +       }
352 +
353 +       if (!info->client) {
354 +               *fd = open_sock(addr->sa_family, type, proto);
355 +               if (*fd < 0)
356 +                       return NULL;
357 +
358 +               if (bind(*fd, laddr, slen) < 0) {
359 +                       close(*fd);
360 +                       return NULL;
361 +               }
362 +       }
363 +
364 +       switch (info->proto->p_proto) {
365 +       case IPPROTO_UDP:
366 +               if (!info->client) {
367 +                       *fd = open_sock(addr->sa_family, type, proto);
368 +                       if (*fd < 0)
369 +                               return NULL;
370 +
371 +                       if (bind(*fd, laddr, slen) < 0) {
372 +                               close(*fd);
373 +                               return NULL;
374 +                       }
375 +               }
376 +               client = rpc_clntudp_create(addr, info, fd);
377 +               break;
378 +
379 +       case IPPROTO_TCP:
380 +               if (!info->client) {
381 +                       *fd = open_sock(addr->sa_family, type, proto);
382 +                       if (*fd < 0)
383 +                               return NULL;
384 +
385 +                       if (connect_nb(*fd, laddr, slen, &info->timeout) < 0) {
386 +                               close(*fd);
387 +                               return NULL;
388 +                       }
389 +               }
390 +               client = rpc_clnttcp_create(addr, info, fd);
391 +               break;
392 +
393 +       default:
394 +               break;
395 +       }
396 +
397 +       return client;
398 +}
399 +
400 +/*
401 + * Create a UDP RPC client
402 + */
403 +static CLIENT *create_udp_client(struct conn_info *info)
404 +{
405 +       CLIENT *client = NULL;
406 +       struct addrinfo *ai, *haddr;
407 +       struct addrinfo hints;
408 +       int fd, ret;
409 +
410 +       if (info->proto->p_proto != IPPROTO_UDP)
411 +               return NULL;
412 +
413 +       fd = RPC_ANYSOCK;
414 +
415 +       if (info->client) {
416 +               if (!clnt_control(info->client, CLGET_FD, (char *) &fd)) {
417 +                       fd = RPC_ANYSOCK;
418 +                       clnt_destroy(info->client);
419 +                       info->client = NULL;
420 +               } else {
421 +                       clnt_control(info->client, CLSET_FD_NCLOSE, NULL);
422 +                       clnt_destroy(info->client);
423 +               }
424 +       }
425 +
426 +       if (info->addr) {
427 +               client = rpc_do_create_client(info->addr, info, &fd);
428 +               if (client)
429 +                       goto done;
430 +
431 +               if (!info->client) {
432 +                       close(fd);
433 +                       fd = RPC_ANYSOCK;
434 +               }
435 +       }
436 +
437 +       memset(&hints, 0, sizeof(hints));
438 +       hints.ai_flags = AI_ADDRCONFIG;
439 +       hints.ai_family = AF_UNSPEC;
440 +       hints.ai_socktype = SOCK_DGRAM;
441 +
442 +       ret = getaddrinfo(info->host, NULL, &hints, &ai);
443 +       if (ret) {
444 +               error(LOGOPT_ANY,
445 +                     "hostname lookup failed: %s", gai_strerror(ret));
446 +               goto out_close;
447 +       }
448 +
449 +       haddr = ai;
450 +       while (haddr) {
451 +               client = rpc_do_create_client(haddr->ai_addr, info, &fd);
452 +               if (client)
453 +                       break;
454 +
455 +               if (!info->client) {
456 +                       close(fd);
457 +                       fd = RPC_ANYSOCK;
458 +               }
459 +
460 +               haddr = haddr->ai_next;
461 +       }
462 +
463 +       freeaddrinfo(ai);
464 +
465 +       if (!client) {
466 +               info->client = NULL;
467 +               goto out_close;
468 +       }
469 +done:
470 +       /* Close socket fd on destroy, as is default for rpcowned fds */
471 +       if  (!clnt_control(client, CLSET_FD_CLOSE, NULL)) {
472 +               clnt_destroy(client);
473 +               info->client = NULL;
474 +               goto out_close;
475 +       }
476 +
477 +       return client;
478 +
479 +out_close:
480 +       if (fd != -1)
481 +               close(fd);
482 +       return NULL;
483 +}
484 +
485 +int rpc_udp_getclient(struct conn_info *info,
486 +                     unsigned int program, unsigned int version)
487 +{
488 +       struct protoent *pe_proto;
489 +       CLIENT *client;
490 +
491 +       if (!info->client) {
492 +               pe_proto = getprotobyname("udp");
493 +               if (!pe_proto)
494 +                       return 0;
495 +
496 +               info->proto = pe_proto;
497 +               info->send_sz = UDPMSGSIZE;
498 +               info->recv_sz = UDPMSGSIZE;
499 +       }
500 +
501 +       info->program = program;
502 +       info->version = version;
503 +
504 +       client = create_udp_client(info);
505 +
506 +       if (!client)
507 +               return 0;
508 +
509 +       info->client = client;
510 +
511 +       return 1;
512 +}
513 +
514 +void rpc_destroy_udp_client(struct conn_info *info)
515 +{
516 +       if (!info->client)
517 +               return;
518 +
519 +       clnt_destroy(info->client);
520 +       info->client = NULL;
521 +       return;
522 +}
523 +
524  /*
525   * Create a TCP RPC client using non-blocking connect
526   */
527  static CLIENT *create_tcp_client(struct conn_info *info)
528  {
529 -       int fd, ghn_errno;
530 -       CLIENT *client;
531 -       struct sockaddr_in addr;
532 -       struct hostent hp;
533 -       struct hostent *php = &hp;
534 -       struct hostent *result;
535 -       char buf[HOST_ENT_BUF_SIZE];
536 -       int ret;
537 +       CLIENT *client = NULL;
538 +       struct addrinfo *ai, *haddr;
539 +       struct addrinfo hints;
540 +       int fd, ret;
541  
542         if (info->proto->p_proto != IPPROTO_TCP)
543                 return NULL;
544  
545 +       fd = RPC_ANYSOCK;
546 +
547         if (info->client) {
548                 if (!clnt_control(info->client, CLGET_FD, (char *) &fd)) {
549 -                       fd = -1;
550 +                       fd = RPC_ANYSOCK;
551                         clnt_destroy(info->client);
552                         info->client = NULL;
553                 } else {
554 @@ -305,51 +450,50 @@ static CLIENT *create_tcp_client(struct conn_info *info)
555                 }
556         }
557  
558 -       memset(&addr, 0, sizeof(addr));
559 -
560 -       addr.sin_family = AF_INET;
561         if (info->addr) {
562 -               memcpy(&addr.sin_addr.s_addr, info->addr, info->addr_len);
563 -               goto got_addr;
564 -       }
565 +               client = rpc_do_create_client(info->addr, info, &fd);
566 +               if (client)
567 +                       goto done;
568  
569 -       if (inet_aton(info->host, &addr.sin_addr))
570 -               goto got_addr;
571 +               if (!info->client) {
572 +                       close(fd);
573 +                       fd = RPC_ANYSOCK;
574 +               }
575 +       }
576  
577 -       memset(&hp, 0, sizeof(struct hostent));
578 +       memset(&hints, 0, sizeof(hints));
579 +       hints.ai_flags = AI_ADDRCONFIG;
580 +       hints.ai_family = AF_UNSPEC;
581 +       hints.ai_socktype = SOCK_STREAM;
582  
583 -       ret = gethostbyname_r(info->host, php,
584 -                       buf, HOST_ENT_BUF_SIZE, &result, &ghn_errno);
585 -       if (ret || !result) {
586 -               int err = ghn_errno == -1 ? errno : ghn_errno;
587 -               char *estr =  strerror_r(err, buf, HOST_ENT_BUF_SIZE);
588 -               logerr("hostname lookup failed: %s", estr);
589 +       ret = getaddrinfo(info->host, NULL, &hints, &ai);
590 +       if (ret) {
591 +               error(LOGOPT_ANY,
592 +                     "hostname lookup failed: %s", gai_strerror(ret));
593                 goto out_close;
594         }
595 -       memcpy(&addr.sin_addr.s_addr, php->h_addr, php->h_length);
596  
597 -got_addr:
598 -       addr.sin_port = htons(info->port);
599 +       haddr = ai;
600 +       while (haddr) {
601 +               client = rpc_do_create_client(haddr->ai_addr, info, &fd);
602 +               if (client)
603 +                       break;
604  
605 -       if (!info->client) {
606 -               fd = open_sock(PF_INET, SOCK_STREAM, info->proto->p_proto);
607 -               if (fd < 0)
608 -                       return NULL;
609 +               if (!info->client) {
610 +                       close(fd);
611 +                       fd = RPC_ANYSOCK;
612 +               }
613  
614 -               ret = connect_nb(fd, &addr, &info->timeout);
615 -               if (ret < 0)
616 -                       goto out_close;
617 +               haddr = haddr->ai_next;
618         }
619  
620 -       client = clnttcp_create(&addr,
621 -                               info->program, info->version, &fd,
622 -                               info->send_sz, info->recv_sz);
623 +       freeaddrinfo(ai);
624  
625         if (!client) {
626                 info->client = NULL;
627                 goto out_close;
628         }
629 -
630 +done:
631         /* Close socket fd on destroy, as is default for rpcowned fds */
632         if  (!clnt_control(client, CLSET_FD_CLOSE, NULL)) {
633                 clnt_destroy(client);
634 @@ -420,7 +564,7 @@ void rpc_destroy_tcp_client(struct conn_info *info)
635  }
636  
637  int rpc_portmap_getclient(struct conn_info *info,
638 -                         const char *host, const char *addr, size_t addr_len,
639 +                         const char *host, struct sockaddr *addr, size_t addr_len,
640                           const char *proto, unsigned int option)
641  {
642         struct protoent *pe_proto;
643 diff --git a/modules/cyrus-sasl.c b/modules/cyrus-sasl.c
644 index 286af15..ec2ab0c 100644
645 --- a/modules/cyrus-sasl.c
646 +++ b/modules/cyrus-sasl.c
647 @@ -732,16 +732,25 @@ sasl_bind_mech(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt, const c
648         debug(logopt, "Attempting sasl bind with mechanism %s", mech);
649  
650         result = ldap_get_option(ldap, LDAP_OPT_HOST_NAME, &host);
651 -       if (result != LDAP_SUCCESS || !host) {
652 +       if (result != LDAP_OPT_SUCCESS || !host) {
653                 debug(logopt, "failed to get hostname for connection");
654                 return NULL;
655         }
656  
657 -       if ((tmp = strchr(host, ':')))
658 -               *tmp = '\0';
659 +       if ((tmp = strrchr(host, ':'))) {
660 +               if (*(tmp - 1) != ']') {
661 +                       *tmp = '\0';
662 +                       tmp = host;
663 +               } else {
664 +                       *(tmp - 1) = '\0';
665 +                       tmp = host;
666 +                       if (*tmp == '[')
667 +                               tmp++;
668 +               }
669 +       }
670  
671         /* Create a new authentication context for the service. */
672 -       result = sasl_client_new("ldap", host, NULL, NULL, NULL, 0, &conn);
673 +       result = sasl_client_new("ldap", tmp, NULL, NULL, NULL, 0, &conn);
674         if (result != SASL_OK) {
675                 error(logopt, "sasl_client_new failed with error %d",
676                       result);
677 diff --git a/modules/replicated.c b/modules/replicated.c
678 index 835af97..9e85c00 100644
679 --- a/modules/replicated.c
680 +++ b/modules/replicated.c
681 @@ -45,7 +45,7 @@
682  #include <stdlib.h>
683  #include <sys/errno.h>
684  #include <sys/types.h>
685 -#include <netinet/in.h>
686 +#include <stdint.h>
687  #include <sys/ioctl.h>
688  #include <sys/socket.h>
689  #include <arpa/inet.h>
690 @@ -75,6 +75,20 @@ static int volatile ifc_last_len = 0;
691  #define max(x, y)      (x >= y ? x : y)
692  #define mmax(x, y, z)  (max(x, y) == x ? max(x, z) : max(y, z))
693  
694 +unsigned int ipv6_mask_cmp(uint32_t *host, uint32_t *iface, uint32_t *mask)
695 +{
696 +       unsigned int ret = 1;
697 +       unsigned int i;
698 +
699 +       for (i = 0; i < 4; i++) {
700 +               if ((host[i] & mask[i]) != (iface[i] & mask[i])) {
701 +                       ret = 0;
702 +                       break;
703 +               }
704 +       }
705 +       return ret;
706 +}
707 +
708  void seed_random(void)
709  {
710         int fd;
711 @@ -136,20 +150,49 @@ static int alloc_ifreq(struct ifconf *ifc, int sock)
712         return 1;
713  }
714  
715 -static unsigned int get_proximity(const char *host_addr, int addr_len)
716 +static unsigned int get_proximity(struct sockaddr *host_addr)
717  {
718 -       struct sockaddr_in *msk_addr, *if_addr;
719 +       struct sockaddr_in *addr, *msk_addr, *if_addr;
720 +       struct sockaddr_in6 *addr6, *msk6_addr, *if6_addr;
721         struct in_addr *hst_addr;
722 -       char tmp[20], buf[MAX_ERR_BUF], *ptr;
723 +       struct in6_addr *hst6_addr;
724 +       int addr_len;
725 +       char buf[MAX_ERR_BUF], *ptr;
726         struct ifconf ifc;
727         struct ifreq *ifr, nmptr;
728         int sock, ret, i;
729 -       uint32_t mask, ha, ia;
730 +       uint32_t mask, ha, ia, *mask6, *ha6, *ia6;
731 +
732 +       addr = NULL;
733 +       addr6 = NULL;
734 +       hst_addr = NULL;
735 +       hst6_addr = NULL;
736 +       mask6 = NULL;
737 +       ha6 = NULL;
738 +       ia6 = NULL;
739 +
740 +       switch (host_addr->sa_family) {
741 +       case AF_INET:
742 +               addr = (struct sockaddr_in *) host_addr;
743 +               hst_addr = (struct in_addr *) &addr->sin_addr;
744 +               ha = ntohl((uint32_t) hst_addr->s_addr);
745 +               addr_len = sizeof(hst_addr);
746 +               break;
747  
748 -       memcpy(tmp, host_addr, addr_len);
749 -       hst_addr = (struct in_addr *) tmp;
750 +       case AF_INET6:
751 +#ifndef INET6
752 +               return PROXIMITY_ERROR;
753 +#else
754 +               addr6 = (struct sockaddr_in6 *) host_addr;
755 +               hst6_addr = (struct in6_addr *) &addr6->sin6_addr;
756 +               ha6 = &hst6_addr->s6_addr32[0];
757 +               addr_len = sizeof(hst6_addr);
758 +               break;
759 +#endif
760  
761 -       ha = ntohl((uint32_t) hst_addr->s_addr);
762 +       default:
763 +               return PROXIMITY_ERROR;
764 +       }
765  
766         sock = open_sock(AF_INET, SOCK_DGRAM, 0);
767         if (sock < 0) {
768 @@ -174,6 +217,10 @@ static unsigned int get_proximity(const char *host_addr, int addr_len)
769  
770                 switch (ifr->ifr_addr.sa_family) {
771                 case AF_INET:
772 +#ifndef INET6
773 +                       if (host_addr->sa_family == AF_INET6)
774 +                               break;
775 +#endif
776                         if_addr = (struct sockaddr_in *) &ifr->ifr_addr;
777                         ret = memcmp(&if_addr->sin_addr, hst_addr, addr_len);
778                         if (!ret) {
779 @@ -183,6 +230,20 @@ static unsigned int get_proximity(const char *host_addr, int addr_len)
780                         }
781                         break;
782  
783 +               case AF_INET6:
784 +#ifndef INET6
785 +                       if (host_addr->sa_family == AF_INET)
786 +                               break;
787 +
788 +                       if6_addr = (struct sockaddr_in6 *) &ifr->ifr_addr;
789 +                       ret = memcmp(&if6_addr->sin6_addr, hst6_addr, addr_len);
790 +                       if (!ret) {
791 +                               close(sock);
792 +                               free(ifc.ifc_req);
793 +                               return PROXIMITY_LOCAL;
794 +                       }
795 +#endif
796 +
797                 default:
798                         break;
799                 }
800 @@ -197,23 +258,27 @@ static unsigned int get_proximity(const char *host_addr, int addr_len)
801         while (ptr < (char *) ifc.ifc_req + ifc.ifc_len) {
802                 ifr = (struct ifreq *) ptr;
803  
804 +               nmptr = *ifr;
805 +               ret = ioctl(sock, SIOCGIFNETMASK, &nmptr);
806 +               if (ret == -1) {
807 +                       char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
808 +                       logerr("ioctl: %s", estr);
809 +                       close(sock);
810 +                       free(ifc.ifc_req);
811 +                       return PROXIMITY_ERROR;
812 +               }
813 +
814                 switch (ifr->ifr_addr.sa_family) {
815                 case AF_INET:
816 +#ifndef INET6
817 +                       if (host_addr->sa_family == AF_INET6)
818 +                               break;
819 +#endif
820                         if_addr = (struct sockaddr_in *) &ifr->ifr_addr;
821                         ia =  ntohl((uint32_t) if_addr->sin_addr.s_addr);
822  
823                         /* Is the address within a localiy attached subnet */
824  
825 -                       nmptr = *ifr;
826 -                       ret = ioctl(sock, SIOCGIFNETMASK, &nmptr);
827 -                       if (ret == -1) {
828 -                               char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
829 -                               logerr("ioctl: %s", estr);
830 -                               close(sock);
831 -                               free(ifc.ifc_req);
832 -                               return PROXIMITY_ERROR;
833 -                       }
834 -
835                         msk_addr = (struct sockaddr_in *) &nmptr.ifr_netmask;
836                         mask = ntohl((uint32_t) msk_addr->sin_addr.s_addr);
837  
838 @@ -247,6 +312,29 @@ static unsigned int get_proximity(const char *host_addr, int addr_len)
839                         }
840                         break;
841  
842 +               case AF_INET6:
843 +#ifndef INET6
844 +                       if (host_addr->sa_family == AF_INET)
845 +                               break;
846 +
847 +                       if6_addr = (struct sockaddr_in6 *) &ifr->ifr_addr;
848 +                       ia6 = &if6_addr->sin6_addr.s6_addr32[0];
849 +
850 +                       /* Is the address within the network of the interface */
851 +
852 +                       msk6_addr = (struct sockaddr_in6 *) &nmptr.ifr_netmask;
853 +                       mask6 = &msk6_addr->sin6_addr.s6_addr32[0];
854 +
855 +                       if (ipv6_mask_cmp(ha6, ia6, mask6)) {
856 +                               close(sock);
857 +                               free(ifc.ifc_req);
858 +                               return PROXIMITY_SUBNET;
859 +                       }
860 +
861 +                       /* How do we define "local network" in ipv6? */
862 +#endif
863 +                       break;
864 +
865                 default:
866                         break;
867                 }
868 @@ -262,11 +350,12 @@ static unsigned int get_proximity(const char *host_addr, int addr_len)
869  }
870  
871  static struct host *new_host(const char *name,
872 -                            const char *addr, size_t addr_len,
873 +                            struct sockaddr *addr, size_t addr_len,
874                              unsigned int proximity, unsigned int weight)
875  {
876         struct host *new;
877 -       char *tmp1, *tmp2;
878 +       struct sockaddr *tmp2;
879 +       char *tmp1;
880  
881         if (!name || !addr)
882                 return NULL;
883 @@ -950,65 +1039,78 @@ int prune_host_list(unsigned logopt, struct host **list,
884         return 1;
885  }
886  
887 -static int add_host_addrs(struct host **list, const char *host, unsigned int weight)
888 +static int add_new_host(struct host **list,
889 +                       const char *host, unsigned int weight,
890 +                       struct addrinfo *host_addr)
891  {
892 -       struct hostent he;
893 -       struct hostent *phe = &he;
894 -       struct hostent *result;
895 -       struct sockaddr_in saddr;
896 -       char buf[MAX_IFC_BUF], **haddr;
897 -       int ghn_errno, ret;
898         struct host *new;
899         unsigned int prx;
900 +       int addr_len;
901  
902 -       saddr.sin_family = AF_INET;
903 -       if (inet_aton(host, &saddr.sin_addr)) {
904 -               const char *thost = (const char *) &saddr.sin_addr;
905 -
906 -               prx = get_proximity(thost, sizeof(saddr.sin_addr));
907 -               if (prx == PROXIMITY_ERROR)
908 -                       return 0;
909 -
910 -               if (!(new = new_host(host, thost, sizeof(saddr.sin_addr), prx, weight)))
911 -                       return 0;
912 -
913 -               if (!add_host(list, new))
914 -                       free_host(new);
915 -
916 -               return 1;
917 -       }
918 +       prx = get_proximity(host_addr->ai_addr);
919 +       if (prx == PROXIMITY_ERROR)
920 +               return 0;
921  
922 -       memset(buf, 0, MAX_IFC_BUF);
923 -       memset(&he, 0, sizeof(struct hostent));
924 +       addr_len = sizeof(struct sockaddr);
925 +       new = new_host(host, host_addr->ai_addr, addr_len, prx, weight);
926 +       if (!new)
927 +               return 0;
928  
929 -       ret = gethostbyname_r(host, phe,
930 -                       buf, MAX_IFC_BUF, &result, &ghn_errno);
931 -       if (ret || !result) {
932 -               if (ghn_errno == -1)
933 -                       logmsg("host %s: lookup failure %d", host, errno);
934 -               else
935 -                       logmsg("host %s: lookup failure %d", host, ghn_errno);
936 +       if (!add_host(list, new)) {
937 +               free_host(new);
938                 return 0;
939         }
940  
941 -       for (haddr = phe->h_addr_list; *haddr; haddr++) {
942 -               struct in_addr tt;
943 +       return 1;
944 +}
945  
946 -               prx = get_proximity(*haddr, phe->h_length);
947 -               if (prx == PROXIMITY_ERROR)
948 -                       return 0;
949 +static int add_host_addrs(struct host **list, const char *host, unsigned int weight)
950 +{
951 +       struct addrinfo hints, *ni, *this;
952 +       int ret;
953  
954 -               memcpy(&tt, *haddr, sizeof(struct in_addr));
955 -               if (!(new = new_host(host, *haddr, phe->h_length, prx, weight)))
956 -                       return 0;
957 +       memset(&hints, 0, sizeof(hints));
958 +       hints.ai_flags = AI_NUMERICHOST;
959 +       hints.ai_family = AF_UNSPEC;
960 +       hints.ai_socktype = SOCK_DGRAM;
961  
962 -               if (!add_host(list, new)) {
963 -                       free_host(new);
964 -                       continue;
965 -               }
966 +       ret = getaddrinfo(host, NULL, &hints, &ni);
967 +       if (ret)
968 +               goto try_name;
969 +
970 +       this = ni;
971 +       while (this) {
972 +               ret = add_new_host(list, host, weight, this);
973 +               if (!ret)
974 +                       break;
975 +               this = this->ai_next;
976 +       }
977 +       freeaddrinfo(ni);
978 +       goto done;
979 +
980 +try_name:
981 +       memset(&hints, 0, sizeof(hints));
982 +       hints.ai_flags = AI_ADDRCONFIG;
983 +       hints.ai_family = AF_UNSPEC;
984 +       hints.ai_socktype = SOCK_DGRAM;
985 +
986 +       ret = getaddrinfo(host, NULL, &hints, &ni);
987 +       if (ret) {
988 +               error(LOGOPT_ANY, "hostname lookup failed: %s",
989 +                     gai_strerror(ret));
990 +               return 0;
991         }
992  
993 -       return 1;
994 +       this = ni;
995 +       while (this) {
996 +               ret = add_new_host(list, host, weight, this);
997 +               if (!ret)
998 +                       break;
999 +               this = this->ai_next;
1000 +       }
1001 +       freeaddrinfo(ni);
1002 +done:
1003 +       return ret;
1004  }
1005  
1006  static int add_path(struct host *hosts, const char *path, int len)
1007 @@ -1057,7 +1159,8 @@ static int add_local_path(struct host **hosts, const char *path)
1008         new->path = tmp;
1009         new->proximity = PROXIMITY_LOCAL;
1010         new->version = NFS_VERS_MASK;
1011 -       new->name = new->addr = NULL;
1012 +       new->name = NULL;
1013 +       new->addr = NULL;
1014         new->weight = new->cost = 0;
1015  
1016         add_host(hosts, new);
This page took 0.223885 seconds and 3 git commands to generate.