From bc598c23dc6141d69167a8bbfbd5f656cf5ccd2c Mon Sep 17 00:00:00 2001 From: Vincent Bernat Date: Fri, 12 Mar 2010 12:03:24 +0100 Subject: [PATCH] Retrieve FD_SETSIZE in a sane environment. Since we import linux/if.h, in some environment, we may end up importing kernel FD_SETSIZE that may be inappropriate (too large). For example, on Sarge systems, FD_SETSIZE becomes 8192 instead of 1024 but FD_ISSET is unable to handle this size. --- configure.ac | 1 + m4/fdsetsize.m4 | 32 ++++++++++++++++++++++++++++++++ src/interfaces.c | 2 +- src/lldpd.c | 12 ++++++++---- 4 files changed, 42 insertions(+), 5 deletions(-) create mode 100644 m4/fdsetsize.m4 diff --git a/configure.ac b/configure.ac index ae684b3f..70510541 100644 --- a/configure.ac +++ b/configure.ac @@ -161,6 +161,7 @@ AC_TYPE_UINT16_T AC_TYPE_UINT32_T AC_TYPE_UINT8_T lldp_CHECK___PROGNAME +lldp_CHECK_FD_SETSIZE # Checks for library functions. AC_FUNC_CHOWN diff --git a/m4/fdsetsize.m4 b/m4/fdsetsize.m4 new file mode 100644 index 00000000..74197f84 --- /dev/null +++ b/m4/fdsetsize.m4 @@ -0,0 +1,32 @@ +# +# lldp_CHECK_FD_SETSIZE +# +AC_DEFUN([lldp_CHECK_FD_SETSIZE],[ + AC_CACHE_CHECK([real value of FD_SETSIZE], lldp_cv_check_fd_setsize, [ + AC_RUN_IFELSE([ + AC_LANG_PROGRAM( + [ +@%:@include +@%:@include +@%:@include +@%:@include +@%:@include + ], + [ + FILE *fd; + if ((fd = fopen("conftest.out", "w")) == NULL) { + printf("Unable to create file conftest.out"); + return 1; + } + fprintf(fd, "%d\n", FD_SETSIZE); + fclose(fd); + ])], + [ lldp_cv_check_fd_setsize=`cat conftest.out` ], + [ lldp_cv_check_fd_setsize="no" ])]) + if test x"$lldp_cv_check_fd_setsize" = x"no"; then + AC_DEFINE([LLDPD_FD_SETSIZE], [FD_SETSIZE], [FD_SETSIZE for select()]) + else + AC_DEFINE_UNQUOTED([LLDPD_FD_SETSIZE], $lldp_cv_check_fd_setsize, + [FD_SETSIZE for select()]) + fi +]) diff --git a/src/interfaces.c b/src/interfaces.c index 18a1e302..5192ee1f 100644 --- a/src/interfaces.c +++ b/src/interfaces.c @@ -602,7 +602,7 @@ static void iface_fds_close(struct lldpd *cfg, struct lldpd_hardware *hardware) { int i; - for (i=0; i < FD_SETSIZE; i++) + for (i=0; i < LLDPD_FD_SETSIZE; i++) if (FD_ISSET(i, &hardware->h_recvfds)) { FD_CLR(i, &hardware->h_recvfds); close(i); diff --git a/src/lldpd.c b/src/lldpd.c index 6e7b974e..98f27708 100644 --- a/src/lldpd.c +++ b/src/lldpd.c @@ -33,6 +33,10 @@ #include #include +#if LLDPD_FD_SETSIZE != FD_SETSIZE +# warning "FD_SETSIZE is set to an inconsistent value." +#endif + #ifdef USE_SNMP #include #include @@ -240,7 +244,7 @@ lldpd_hardware_cleanup(struct lldpd *cfg, struct lldpd_hardware *hardware) hardware->h_ops->cleanup(cfg, hardware); else { free(hardware->h_data); - for (i=0; i < FD_SETSIZE; i++) + for (i=0; i < LLDPD_FD_SETSIZE; i++) if (FD_ISSET(i, &hardware->h_recvfds)) close(i); if (hardware->h_sendfd) close(hardware->h_sendfd); @@ -482,7 +486,7 @@ lldpd_recv_all(struct lldpd *cfg) continue; /* This is quite expensive but we don't rely on internal * structure of fd_set. */ - for (n = 0; n < FD_SETSIZE; n++) + for (n = 0; n < LLDPD_FD_SETSIZE; n++) if (FD_ISSET(n, &hardware->h_recvfds)) { FD_SET(n, &rfds); if (nfds < n) @@ -520,10 +524,10 @@ lldpd_recv_all(struct lldpd *cfg) } #endif /* USE_SNMP */ TAILQ_FOREACH(hardware, &cfg->g_hardware, h_entries) { - for (n = 0; n < FD_SETSIZE; n++) + for (n = 0; n < LLDPD_FD_SETSIZE; n++) if ((FD_ISSET(n, &hardware->h_recvfds)) && (FD_ISSET(n, &rfds))) break; - if (n == FD_SETSIZE) continue; + if (n == LLDPD_FD_SETSIZE) continue; if ((buffer = (char *)malloc( hardware->h_mtu)) == NULL) { LLOG_WARN("failed to alloc reception buffer"); -- 2.39.5