Hello again, I think this is a regression, since now it will refuse all IPv4 connections. I filed a new PR on github [0].
[0] https://github.com/apache/apr/pull/44 Best, Lubos Uhliarik On Fri, Jun 23, 2023 at 1:04 PM Lubos Uhliarik <luhli...@redhat.com> wrote: > Hello all, > > I have recently created PR [0], which has been merged and I backported > this patch to our latest apr-util version in Fedora. > > Now I have been trying to come up with some test. I created simple C file > where I'm trying to query memcached: > > int main(int argc, char **argv) > { > apr_pool_t *pglobal; > apr_status_t rv; > char *mcversion; > char *errstr = malloc(1024); > > apr_app_initialize(NULL, NULL, NULL); > > if (apr_pool_create(&pglobal, NULL)){ > fprintf(stderr, "could not create global pool"); > return 1; > } > > if (argc != 3){ > fprintf(stderr, "Usage: ./connconnectipv6 HOST PORT\n"); > return 2; > } > > apr_memcache_server_t *ms; > > rv = apr_memcache_server_create(pglobal, argv[1], atoi(argv[2]), 0, 2, > 2, 60, &ms); > if (rv != APR_SUCCESS){. > fprintf(stderr, "Errno: %d - %s\n", errno, apr_strerror(errno, > errstr, 1024)); > return 3; > } > > rv = apr_memcache_version(ms, pglobal, &mcversion); > if (rv != APR_SUCCESS){. > fprintf(stderr, "Errno: %d - %s\n", errno, apr_strerror(errno, > errstr, 1024)); > return 5; > } > > fprintf(stdout, "memcached version: %s\n", mcversion); > > apr_pool_destroy(pglobal); > free(errstr); > > return 0; > } > > > > In old apr-util version without patch[0] , I'm getting output as expected: > > # ./memcachecon 127.0.0.1 11211 > memcached version: 1.6.21 > # echo $? > 0 > # ./memcachecon ::1 11211 > Errno: 0 - Success > # echo $? > 5 > > But with new apr-util containing patch[0], I'm getting weird behavior: > > # ./memcachecon 127.0.0.1 11211 > Errno: 22 - Invalid argument > # echo $? > 5 > # ./memcachecon ::1 11211 > memcached version: 1.6.21 > # echo $? > 0 > > I don't know why, but somehow I'm getting errcode 22 in mc_conn_construct > function allegedly returned by conn_connect, but when I debug it in gdb it > shows me that conn_connect returns 0. Also it looks like > apr_socketaddr_info_get finished successfully. I'm really puzzled here. Do > you have any idea, what am I doing wrong? > > Also adding output from gdb: > > (gdb) run 127.0.0.1 11211 > Starting program: /tmp/tmp.ntb0HNhuvT/memcachecon 127.0.0.1 11211 > [Thread debugging using libthread_db enabled] > Using host libthread_db library "/lib64/libthread_db.so.1". > > Breakpoint 2, apr_sockaddr_info_get (sa=sa@entry=0x7fffffffd9f0, > hostname=0x40b490 "127.0.0.1", family=0, port=11211, flags=flags@entry=0, > p=0x40d3f8) at network_io/unix/sockaddr.c:639 > 639 { > (gdb) list > 634 > 635 APR_DECLARE(apr_status_t) apr_sockaddr_info_get(apr_sockaddr_t **sa, > 636 const char *hostname, > 637 apr_int32_t family, > apr_port_t port, > 638 apr_int32_t flags, > apr_pool_t *p) > 639 { > 640 apr_int32_t masked; > 641 *sa = NULL; > 642 > 643 if ((masked = flags & (APR_IPV4_ADDR_OK | APR_IPV6_ADDR_OK))) { > (gdb) > 644 if (!hostname || > 645 family != APR_UNSPEC || > 646 masked == (APR_IPV4_ADDR_OK | APR_IPV6_ADDR_OK)) { > 647 return APR_EINVAL; > 648 } > 649 #if !APR_HAVE_IPV6 > 650 if (flags & APR_IPV6_ADDR_OK) { > 651 return APR_ENOTIMPL; > 652 } > 653 #endif > (gdb) > 654 } > 655 if (family == APR_UNSPEC && hostname && *hostname == '/') { > 656 family = APR_UNIX; > 657 } > 658 if (family == APR_UNIX) { > 659 #if APR_HAVE_SOCKADDR_UN > 660 if (hostname && *hostname == '/') { > 661 *sa = apr_pcalloc(p, sizeof(apr_sockaddr_t)); > 662 (*sa)->pool = p; > 663 apr_cpystrn((*sa)->sa.unx.sun_path, hostname, > (gdb) > 664 sizeof((*sa)->sa.unx.sun_path)); > 665 (*sa)->hostname = apr_pstrdup(p, hostname); > 666 (*sa)->family = APR_UNIX; > 667 (*sa)->sa.unx.sun_family = APR_UNIX; > 668 (*sa)->salen = sizeof(struct sockaddr_un); > 669 (*sa)->addr_str_len = sizeof((*sa)->sa.unx.sun_path); > 670 (*sa)->ipaddr_ptr = &((*sa)->sa.unx.sun_path); > 671 (*sa)->ipaddr_len = (*sa)->addr_str_len; > 672 > 673 return APR_SUCCESS; > (gdb) > 674 } > 675 else > 676 #endif > 677 { > 678 *sa = NULL; > 679 return APR_ENOTIMPL; > 680 } > 681 } > 682 #if !APR_HAVE_IPV6 > 683 /* What may happen is that APR is not IPv6-enabled, but we're still > (gdb) > 684 * going to call getaddrinfo(), so we have to tell the OS we only > 685 * want IPv4 addresses back since we won't know what to do with > 686 * IPv6 addresses. > 687 */ > 688 if (family == APR_UNSPEC) { > 689 family = APR_INET; > 690 } > 691 #endif > 692 > 693 return find_addresses(sa, hostname, family, port, flags, p); > (gdb) > 694 } > 695 > 696 APR_DECLARE(apr_status_t) apr_sockaddr_info_copy(apr_sockaddr_t **dst, > 697 const apr_sockaddr_t > *src, > 698 apr_pool_t *p) > 699 { > 700 apr_sockaddr_t *d; > 701 const apr_sockaddr_t *s; > 702 > 703 for (*dst = d = NULL, s = src; s; s = s->next) { > (gdb) > 704 if (!d) { > 705 *dst = d = apr_pmemdup(p, s, sizeof *s); > 706 } > 707 else { > 708 d = d->next = apr_pmemdup(p, s, sizeof *s); > 709 } > 710 if (s->hostname) { > 711 if (s == src || s->hostname != src->hostname) { > 712 d->hostname = apr_pstrdup(p, s->hostname); > 713 } > (gdb) n > 641 *sa = NULL; > (gdb) > 643 if ((masked = flags & (APR_IPV4_ADDR_OK | APR_IPV6_ADDR_OK))) { > (gdb) > 655 if (family == APR_UNSPEC && hostname && *hostname == '/') { > (gdb) > 693 return find_addresses(sa, hostname, family, port, flags, p); > (gdb) > call_resolver.constprop.0 (sa=sa@entry=0x7fffffffd9f0, hostname=0x40b490 > "127.0.0.1", family=0, port=11211, p=0x40d3f8, flags=<optimized out>) at > network_io/unix/sockaddr.c:337 > 337 static apr_status_t call_resolver(apr_sockaddr_t **sa, > (gdb) > 347 memset(&hints, 0, sizeof(hints)); > (gdb) > 337 static apr_status_t call_resolver(apr_sockaddr_t **sa, > (gdb) > 347 memset(&hints, 0, sizeof(hints)); > (gdb) > 337 static apr_status_t call_resolver(apr_sockaddr_t **sa, > (gdb) > 347 memset(&hints, 0, sizeof(hints)); > (gdb) > 348 hints.ai_family = family; > (gdb) > 349 hints.ai_socktype = SOCK_STREAM; > (gdb) > 347 memset(&hints, 0, sizeof(hints)); > (gdb) > 351 if (family == APR_UNSPEC) { > (gdb) > 355 hints.ai_flags = AI_ADDRCONFIG; > (gdb) > 368 if(hostname == NULL) { > (gdb) > 397 error = getaddrinfo(hostname, servname, &hints, &ai_list); > (gdb) > 345 char *servname = NULL; > (gdb) > 397 error = getaddrinfo(hostname, servname, &hints, &ai_list); > (gdb) > 416 || error == EAI_ADDRFAMILY > (gdb) > 414 if ((family == APR_UNSPEC) && (error == EAI_BADFLAGS > (gdb) > 423 if (error) { > (gdb) > 446 ai = ai_list; > (gdb) > 447 while (ai) { /* while more addresses to report */ > (gdb) > 445 prev_sa = NULL; > (gdb) > 454 if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) { > (gdb) > 462 new_sa = apr_pcalloc(p, sizeof(apr_sockaddr_t)); > (gdb) > 464 new_sa->pool = p; > (gdb) > 465 memcpy(&new_sa->sa, ai->ai_addr, ai->ai_addrlen); > (gdb) > 466 apr_sockaddr_vars_set(new_sa, ai->ai_family, port); > (gdb) > 468 if (!prev_sa) { /* first element in new list */ > (gdb) > 469 if (hostname) { > (gdb) > 470 new_sa->hostname = apr_pstrdup(p, hostname); > (gdb) > 472 *sa = new_sa; > (gdb) > 480 ai = ai->ai_next; > (gdb) > 447 while (ai) { /* while more addresses to report */ > (gdb) > 482 freeaddrinfo(ai_list); > (gdb) > 484 if (prev_sa == NULL) { > (gdb) > 493 } > (gdb) > conn_connect (conn=0x40d470) at memcache/apr_memcache.c:299 > 299 if (rv != APR_SUCCESS) { > (gdb) p rv > $1 = 0 > (gdb) l > 294 #else > 295 apr_int32_t family = APR_UNSPEC; > 296 #endif > 297 > 298 rv = apr_sockaddr_info_get(&sa, conn->ms->host, family, > conn->ms->port, 0, conn->p); > 299 if (rv != APR_SUCCESS) { > 300 return rv; > 301 } > 302 > 303 rv = apr_socket_timeout_set(conn->sock, 1 * APR_USEC_PER_SEC); > (gdb) > 304 if (rv != APR_SUCCESS) { > 305 return rv; > 306 } > 307 > 308 rv = apr_socket_connect(conn->sock, sa); > 309 if (rv != APR_SUCCESS) { > 310 return rv; > 311 } > 312 > 313 rv = apr_socket_timeout_set(conn->sock, -1); > (gdb) > 314 if (rv != APR_SUCCESS) { > 315 return rv; > 316 } > 317 > 318 return rv; > 319 } > 320 > 321 > 322 static apr_status_t > 323 mc_conn_construct(void **conn_, void *params, apr_pool_t *pool) > (gdb) bt > #0 conn_connect (conn=0x40d470) at memcache/apr_memcache.c:299 > #1 mc_conn_construct (conn_=0x40b638, params=0x40b460, pool=<optimized > out>) at memcache/apr_memcache.c:363 > #2 0x00007ffff7cff75d in create_resource (ret_res=<synthetic pointer>, > reslist=0x40b4f0) at misc/apr_reslist.c:123 > #3 apr_reslist_acquire (reslist=0x40b4f0, > resource=resource@entry=0x7fffffffda78) > at misc/apr_reslist.c:395 > #4 0x00007ffff7d060fc in ms_find_conn (ms=<optimized out>, ms=<optimized > out>, conn=0x7fffffffda78) at memcache/apr_memcache.c:232 > #5 apr_memcache_version (ms=0x40b460, p=0x4093d8, baton=0x7fffffffdb08) > at memcache/apr_memcache.c:1063 > #6 0x000000000040129e in main (argc=3, argv=0x7fffffffdc38) at > /mnt/tests/CoreOS/apr-util/memcache/bz2063562-memcache-conn-connect-allow-ipv6/connconnectipv6.c:39 > (gdb) n > mc_conn_construct (conn_=0x40b638, params=0x40b460, pool=<optimized out>) > at memcache/apr_memcache.c:363 > 363 rv = conn_connect(conn); > (gdb) p rv > $2 = <optimized out> > (gdb) list > 358 > 359 conn->buffer = apr_palloc(conn->p, BUFFER_SIZE + 1); > 360 conn->blen = 0; > 361 conn->ms = ms; > 362 > 363 rv = conn_connect(conn); > 364 if (rv != APR_SUCCESS) { > 365 apr_pool_destroy(np); > 366 } > 367 else { > (gdb) > 368 *conn_ = conn; > 369 } > 370 > 371 return rv; > 372 } > 373 > 374 #if APR_HAS_THREADS > 375 static apr_status_t > 376 mc_conn_destruct(void *conn_, void *params, apr_pool_t *pool) > 377 { > (gdb) n > 365 apr_pool_destroy(np); > (gdb) p rv > $3 = 22 > (gdb) > > [0] > https://github.com/apache/apr-util/commit/fb3feebd617f6aa904d9132618649f24821bd67f > > Best, > Lubos Uhliarik > -- Luboš Uhliarik Senior Software Engineer | Infrastructure Services luhli...@redhat.com BRQ-TPBC *irc (luhliari at): #brno, #infrastructure-services, #core-services* <https://www.redhat.com/>