@@ -257,7 +257,7 @@ int ping_snmp(host_t *host, ping_t *ping) {
257257 *
258258 */
259259int ping_icmp (host_t * host , ping_t * ping ) {
260- int icmp_socket ;
260+ int icmp_fd ;
261261
262262 double begin_time , end_time , total_time ;
263263 double host_timeout ;
@@ -286,49 +286,21 @@ int ping_icmp(host_t *host, ping_t *ping) {
286286 SPINE_LOG_DEBUG (("DEBUG: Device[%i] Entering ICMP Ping" , host -> id ));
287287 }
288288
289- /* get ICMP socket */
290- retry_count = 0 ;
291- while (TRUE) {
292- #if !(defined(__CYGWIN__ ) && !defined(SOLAR_PRIV ))
293- if (hasCaps () != TRUE) {
294- thread_mutex_lock (LOCK_SETEUID );
295- if (seteuid (0 ) == -1 ) {
296- SPINE_LOG_DEBUG (("WARNING: Spine unable to obtain root privileges." ));
297- }
298- }
299- #endif
300-
301- if ((icmp_socket = socket (AF_INET , SOCK_RAW , IPPROTO_ICMP )) == -1 ) {
302- usleep (500000 );
303- retry_count ++ ;
304-
305- if (retry_count > 4 ) {
306- snprintf (ping -> ping_response , SMALL_BUFSIZE , "ICMP: Ping unable to create ICMP Socket" );
307- snprintf (ping -> ping_status , 50 , "down" );
308- #if !(defined(__CYGWIN__ ) && !defined(SOLAR_PRIV ))
309- if (hasCaps () != TRUE) {
310- if (seteuid (getuid ()) == -1 ) {
311- SPINE_LOG_DEBUG (("WARNING: Spine unable to drop from root to local user." ));
312- }
313- thread_mutex_unlock (LOCK_SETEUID );
314- }
315- #endif
316-
317- return HOST_DOWN ;
318- }
319- } else {
320- break ;
321- }
289+ /* Use the pre-opened global ICMP socket (opened single-threaded in main
290+ * before any worker threads start, eliminating the seteuid race).
291+ * dup() gives each thread its own fd so select()/close() don't interfere. */
292+ if (icmp_socket < 0 ) {
293+ snprintf (ping -> ping_response , SMALL_BUFSIZE , "ICMP: raw socket not available" );
294+ snprintf (ping -> ping_status , 50 , "down" );
295+ return HOST_DOWN ;
322296 }
323297
324- #if !(defined(__CYGWIN__ ) && !defined(SOLAR_PRIV ))
325- if (hasCaps () != TRUE) {
326- if (seteuid (getuid ()) == -1 ) {
327- SPINE_LOG_DEBUG (("WARNING: Spine unable to drop from root to local user." ));
328- }
329- thread_mutex_unlock (LOCK_SETEUID );
298+ icmp_fd = dup (icmp_socket );
299+ if (icmp_fd < 0 ) {
300+ snprintf (ping -> ping_response , SMALL_BUFSIZE , "ICMP: socket dup failed: %s" , strerror (errno ));
301+ snprintf (ping -> ping_status , 50 , "down" );
302+ return HOST_DOWN ;
330303 }
331- #endif
332304
333305 /* convert the host timeout to a double precision number in seconds */
334306 host_timeout = host -> ping_timeout ;
@@ -359,7 +331,7 @@ int ping_icmp(host_t *host, ping_t *ping) {
359331 icmp -> icmp_cksum = get_checksum (packet , packet_len );
360332
361333 /* hostname must be nonblank */
362- if (( strlen (host -> hostname ) != 0 ) && ( icmp_socket != -1 ) ) {
334+ if (strlen (host -> hostname ) != 0 ) {
363335 /* initialize variables */
364336 snprintf (ping -> ping_status , 50 , "down" );
365337 snprintf (ping -> ping_response , SMALL_BUFSIZE , "default" );
@@ -375,7 +347,7 @@ int ping_icmp(host_t *host, ping_t *ping) {
375347 snprintf (ping -> ping_response , SMALL_BUFSIZE , "ICMP: Ping timed out" );
376348 snprintf (ping -> ping_status , 50 , "down" );
377349 free (packet );
378- close (icmp_socket );
350+ close (icmp_fd );
379351 return HOST_DOWN ;
380352 }
381353
@@ -390,27 +362,27 @@ int ping_icmp(host_t *host, ping_t *ping) {
390362 timeout .tv_usec = ((int ) (host_timeout - total_time ) % 1000 ) * 1000 ;
391363
392364 /* set the socket send and receive timeout */
393- setsockopt (icmp_socket , SOL_SOCKET , SO_RCVTIMEO , (char * )& timeout , sizeof (timeout ));
394- setsockopt (icmp_socket , SOL_SOCKET , SO_SNDTIMEO , (char * )& timeout , sizeof (timeout ));
365+ setsockopt (icmp_fd , SOL_SOCKET , SO_RCVTIMEO , (char * )& timeout , sizeof (timeout ));
366+ setsockopt (icmp_fd , SOL_SOCKET , SO_SNDTIMEO , (char * )& timeout , sizeof (timeout ));
395367
396368 /* send packet to destination */
397- return_code = sendto (icmp_socket , packet , packet_len , 0 , (struct sockaddr * ) & fromname , sizeof (fromname ));
369+ return_code = sendto (icmp_fd , packet , packet_len , 0 , (struct sockaddr * ) & fromname , sizeof (fromname ));
398370
399371 fromlen = sizeof (fromname );
400372
401373 /* wait for a response on the socket */
402374 /* reinitialize fd_set -- select(2) clears bits in place on return */
403375 keep_listening :
404376 FD_ZERO (& socket_fds );
405- if (icmp_socket >= FD_SETSIZE ) {
406- SPINE_LOG (("ERROR: Device[%i] ICMP socket %d exceeds FD_SETSIZE %d" , host -> id , icmp_socket , FD_SETSIZE ));
377+ if (icmp_fd >= FD_SETSIZE ) {
378+ SPINE_LOG (("ERROR: Device[%i] ICMP socket %d exceeds FD_SETSIZE %d" , host -> id , icmp_fd , FD_SETSIZE ));
407379 snprintf (ping -> ping_status , 50 , "down" );
408380 snprintf (ping -> ping_response , SMALL_BUFSIZE , "ICMP: fd exceeds FD_SETSIZE" );
409- close (icmp_socket );
381+ close (icmp_fd );
410382 return HOST_DOWN ;
411383 }
412- FD_SET (icmp_socket ,& socket_fds );
413- return_code = select (icmp_socket + 1 , & socket_fds , NULL , NULL , & timeout );
384+ FD_SET (icmp_fd ,& socket_fds );
385+ return_code = select (icmp_fd + 1 , & socket_fds , NULL , NULL , & timeout );
414386
415387 /* record end time */
416388 end_time = get_time_as_double ();
@@ -420,9 +392,9 @@ int ping_icmp(host_t *host, ping_t *ping) {
420392
421393 if (total_time < host_timeout ) {
422394 #if !(defined(__CYGWIN__ ))
423- return_code = recvfrom (icmp_socket , socket_reply , BUFSIZE , MSG_WAITALL , (struct sockaddr * ) & recvname , & fromlen );
395+ return_code = recvfrom (icmp_fd , socket_reply , BUFSIZE , MSG_WAITALL , (struct sockaddr * ) & recvname , & fromlen );
424396 #else
425- return_code = recvfrom (icmp_socket , socket_reply , BUFSIZE , MSG_PEEK , (struct sockaddr * ) & recvname , & fromlen );
397+ return_code = recvfrom (icmp_fd , socket_reply , BUFSIZE , MSG_PEEK , (struct sockaddr * ) & recvname , & fromlen );
426398 #endif
427399
428400 if (return_code < 0 ) {
@@ -451,24 +423,7 @@ int ping_icmp(host_t *host, ping_t *ping) {
451423 snprintf (ping -> ping_response , SMALL_BUFSIZE , "ICMP: Device is Alive" );
452424 snprintf (ping -> ping_status , 50 , "%.5f" , total_time );
453425 free (packet );
454- #if !(defined(__CYGWIN__ ) && !defined(SOLAR_PRIV ))
455- if (hasCaps () != TRUE) {
456- thread_mutex_lock (LOCK_SETEUID );
457- if (seteuid (0 ) == -1 ) {
458- SPINE_LOG_DEBUG (("WARNING: Spine unable to obtain root privileges." ));
459- }
460- }
461- #endif
462- close (icmp_socket );
463- #if !(defined(__CYGWIN__ ) && !defined(SOLAR_PRIV ))
464- if (hasCaps () != TRUE) {
465- if (seteuid (getuid ()) == -1 ) {
466- SPINE_LOG_DEBUG (("WARNING: Spine unable to drop from root to local user." ));
467- }
468- thread_mutex_unlock (LOCK_SETEUID );
469- }
470- #endif
471-
426+ close (icmp_fd );
472427 return HOST_UP ;
473428 } else {
474429 /* received a response other than an echo reply */
@@ -502,48 +457,14 @@ int ping_icmp(host_t *host, ping_t *ping) {
502457 snprintf (ping -> ping_response , SMALL_BUFSIZE , "ICMP: Destination hostname invalid" );
503458 snprintf (ping -> ping_status , 50 , "down" );
504459 free (packet );
505- #if !(defined(__CYGWIN__ ) && !defined(SOLAR_PRIV ))
506- if (hasCaps () != TRUE) {
507- thread_mutex_lock (LOCK_SETEUID );
508- if (seteuid (0 ) == -1 ) {
509- SPINE_LOG_DEBUG (("WARNING: Spine unable to obtain root privileges." ));
510- }
511- }
512- #endif
513- close (icmp_socket );
514- #if !(defined(__CYGWIN__ ) && !defined(SOLAR_PRIV ))
515- if (hasCaps () != TRUE) {
516- if (seteuid (getuid ()) == -1 ) {
517- SPINE_LOG_DEBUG (("WARNING: Spine unable to drop from root to local user." ));
518- }
519- thread_mutex_unlock (LOCK_SETEUID );
520- }
521- #endif
460+ close (icmp_fd );
522461 return HOST_DOWN ;
523462 }
524463 } else {
525464 snprintf (ping -> ping_response , SMALL_BUFSIZE , "ICMP: Destination address not specified" );
526465 snprintf (ping -> ping_status , 50 , "down" );
527466 free (packet );
528- if (icmp_socket != -1 ) {
529- #if !(defined(__CYGWIN__ ) && !defined(SOLAR_PRIV ))
530- if (hasCaps () != TRUE) {
531- thread_mutex_lock (LOCK_SETEUID );
532- if (seteuid (0 ) == -1 ) {
533- SPINE_LOG_DEBUG (("WARNING: Spine unable to obtain root privileges." ));
534- }
535- }
536- #endif
537- close (icmp_socket );
538- #if !(defined(__CYGWIN__ ) && !defined(SOLAR_PRIV ))
539- if (hasCaps () != TRUE) {
540- if (seteuid (getuid ()) == -1 ) {
541- SPINE_LOG_DEBUG (("WARNING: Spine unable to drop from root to local user." ));
542- }
543- thread_mutex_unlock (LOCK_SETEUID );
544- }
545- #endif
546- }
467+ close (icmp_fd );
547468 return HOST_DOWN ;
548469 }
549470}
0 commit comments