Обсуждение: compile error via SIOCGLIFCONF from ip.c on hpux-11
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. for example, we have: struct if_laddrreq { char iflr_name[IF_NAMESIZE]; /* if name, e.g. "lan0" */ union { struct sockaddr_ext iflru_addr; struct sockaddr_ext iflru_dstaddr; int iflru_flags; #if defined(__STDC_EXT__) || defined(__LP64__) uint64_t iflru_xflags; #endif int iflru_metric; struct iflife iflru_lifetimes; caddr_t iflru_data; unsigned char __iflru_padding[32]; /* alignment for 32/64bit*/ } iflr_iflru; which is similar to struct ifreq { char ifr_name[IFNAMSIZ]; /* Interface name */ union { struct sockaddr ifr_addr; struct sockaddr ifr_dstaddr; struct sockaddr ifr_broadaddr; struct sockaddr ifr_netmask; struct sockaddr ifr_hwaddr; short ifr_flags; int ifr_ifindex; int ifr_metric; int ifr_mtu; struct ifmap ifr_map; char ifr_slave[IFNAMSIZ]; char ifr_newname[IFNAMSIZ]; char * ifr_data; }; }; (via http://unixhelp.ed.ac.uk/CGI/man-cgi?netdevice+7) forcing the #if check of SIOCGLIFCONF to false allowed postgres to continue and compile. Searching the archives turned up the samehost/samenet patch...did that break this? was hpux checked, or is this a version issue? (I'm testing on 11.23 Itanium). merlin
Merlin Moncure <mmoncure@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 regards, tom lane
On Mon, Nov 29, 2010 at 1:38 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote: > Merlin Moncure <mmoncure@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 * indicationof 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; }
Merlin Moncure <mmoncure@gmail.com> writes: > How do you test this feature? Try src/tools/ifaddrs/test_ifaddrs.c. I think the only usage in the core code is testing samehost/samenet matches in pg_hba.conf. regards, tom lane
On Mon, Nov 29, 2010 at 2:26 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote: > Merlin Moncure <mmoncure@gmail.com> writes: >> How do you test this feature? > > Try src/tools/ifaddrs/test_ifaddrs.c. I think the only usage in the > core code is testing samehost/samenet matches in pg_hba.conf. It looks like this is unfortunately more involved. The test of my adjustment above immediately failed with ENOENT, which you have to expect on hpux apparently. According to some googling (see: http://cvsweb.netbsd.org/bsdweb.cgi/src/dist/bind/lib/isc/unix/Attic/ifiter_ioctl.c?rev=1.1.1.4.4.1&content-type=text/x-cvsweb-markup and others), the long method returns ip6 addresses and the short method returns ip4 addresses, and you have to do both on hpux always. Forcing the short method, the test worked, I got the loopback and the local address. So we have a couple of options here: hacking the foreach to use the short method on hpux is certainly better situation than we have now, or fixing this 'properly', means refactoring this file a bit and adding a configure test or leaning on an hpux macro. I have no way of testing the long form method I posed above -- does anybody have an ipv6 hpux box? merlin