On Mon, Nov 29, 2010 at 1:38 PM, Tom Lane <t...@sss.pgh.pa.us> wrote:
> Merlin Moncure <mmonc...@gmail.com> writes:
>> PostgreSQL 9 is breaking for me on line 654 of ip.c.  ip.c is checking
>> on presence SIOCGLIFCONF to determine if it's ok to use linux method
>> of polling if addrs etc over ioctl, which is not enough. hpux provides
>> this method in similar fashion, but the structs are named different,
>> and have different members.
>
> This was complained of last month, and the situation has not changed:
> http://archives.postgresql.org/pgsql-general/2010-10/msg00408.php

well, what should the fix be?  checking on presence of SIOCGLIFCONF is
obviously weak sauce...it looks like some type of configure check is
needed  I converted the function to a version that compiles clean on
hpux (note, I couldn't figure out how to set family, maybe that's not
required?).  How do you test this feature?

merlin

int
pg_foreach_ifaddr(PgIfAddrCallback callback, void *cb_data)
{
        struct if_laddrconf lifc;
        struct  if_laddrreq *lifr,
                                lmask;
        struct sockaddr *addr,
                           *mask;
        char       *ptr,
                           *buffer = NULL;
        size_t          n_buffer = 1024;
        pgsocket        sock,
                                fd;

#ifdef HAVE_IPV6
        pgsocket        sock6;
#endif
        int                     i,
                                total;

        sock = socket(AF_INET, SOCK_DGRAM, 0);
        if (sock == -1)
                return -1;

        while (n_buffer < 1024 * 100)
        {
                n_buffer += 1024;
                ptr = realloc(buffer, n_buffer);
                if (!ptr)
                {
                        free(buffer);
                        close(sock);
                        errno = ENOMEM;
                        return -1;
                }

                memset(&lifc, 0, sizeof(lifc));
                /* XXX how to set family? lifc.iflc_family = AF_UNSPEC; */
                lifc.iflc_buf = buffer = ptr;
                lifc.iflc_len = n_buffer;

                if (ioctl(sock, SIOCGLIFCONF, &lifc) < 0)
                {
                        if (errno == EINVAL)
                                continue;
                        free(buffer);
                        close(sock);
                        return -1;
                }

                /*
                 * Some Unixes try to return as much data as possible, with no
                 * indication of whether enough space allocated. Don't
believe we have
                 * it all unless there's lots of slop.
                 */
                if (lifc.iflc_len < n_buffer - 1024)
                        break;
       }

#ifdef HAVE_IPV6
        /* We'll need an IPv6 socket too for the SIOCGLIFNETMASK ioctls */
        sock6 = socket(AF_INET6, SOCK_DGRAM, 0);
        if (sock6 == -1)
        {
                free(buffer);
                close(sock);
                return -1;
        }
#endif

        total = lifc.iflc_len / sizeof(struct lifreq);
        lifr = lifc.iflc_req;
        for (i = 0; i < total; ++i)
        {
                addr = (struct sockaddr *) & lifr[i].iflr_addr;
                memcpy(&lmask, &lifr[i], sizeof(struct lifreq));
#ifdef HAVE_IPV6
                fd = (addr->sa_family == AF_INET6) ? sock6 : sock;
#else
                fd = sock;
#endif
                if (ioctl(fd, SIOCGLIFNETMASK, &lmask) < 0)
                        mask = NULL;
                else
                        mask = (struct sockaddr *) & lmask.iflr_addr;
                run_ifaddr_callback(callback, cb_data, addr, mask);
        }

        free(buffer);
        close(sock);
#ifdef HAVE_IPV6
        close(sock6);
#endif
        return 0;
}

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to