File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / mtr / packet / packet.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 00:07:30 2021 UTC (3 years, 4 months ago) by misho
Branches: mtr, MAIN
CVS tags: v0_94, HEAD
mtr 0.94

    1: /*
    2:     mtr  --  a network diagnostic tool
    3:     Copyright (C) 2016  Matt Kimball
    4: 
    5:     This program is free software; you can redistribute it and/or modify
    6:     it under the terms of the GNU General Public License version 2 as
    7:     published by the Free Software Foundation.
    8: 
    9:     This program is distributed in the hope that it will be useful,
   10:     but WITHOUT ANY WARRANTY; without even the implied warranty of
   11:     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12:     GNU General Public License for more details.
   13: 
   14:     You should have received a copy of the GNU General Public License along
   15:     with this program; if not, write to the Free Software Foundation, Inc.,
   16:     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   17: */
   18: 
   19: #include "config.h"
   20: 
   21: #include <errno.h>
   22: #ifdef HAVE_ERROR_H
   23: #include <error.h>
   24: #else
   25: #include "portability/error.h"
   26: #endif
   27: #include <stdio.h>
   28: #include <stdlib.h>
   29: #include <string.h>
   30: #include <unistd.h>
   31: 
   32: #ifdef HAVE_LIBCAP
   33: #include <sys/capability.h>
   34: #endif
   35: 
   36: #include "wait.h"
   37: 
   38: /*  Drop SUID privileges.  To be used after accquiring raw sockets.  */
   39: static
   40: int drop_elevated_permissions(
   41:     void)
   42: {
   43: #ifdef HAVE_LIBCAP
   44:     cap_t cap;
   45: #endif
   46: 
   47:     /*  Drop any suid permissions granted  */
   48:     if (setgid(getgid()) || setuid(getuid())) {
   49:         return -1;
   50:     }
   51: 
   52:     if (geteuid() != getuid() || getegid() != getgid()) {
   53:         return -1;
   54:     }
   55: 
   56:     /*
   57:        Drop all process capabilities.
   58:        This will revoke anything granted by a commandline 'setcap'
   59:      */
   60: #ifdef HAVE_LIBCAP
   61:     cap = cap_get_proc();
   62:     if (cap == NULL) {
   63:         return -1;
   64:     }
   65:     if (cap_clear(cap)) {
   66:         return -1;
   67:     }
   68:     if (cap_set_proc(cap)) {
   69:         return -1;
   70:     }
   71: #endif
   72: 
   73:     return 0;
   74: }
   75: 
   76: int main(
   77:     int argc,
   78:     char **argv)
   79: {
   80:     bool command_pipe_open;
   81:     struct command_buffer_t command_buffer;
   82:     struct net_state_t net_state;
   83: 
   84:     /*
   85:        To minimize security risk, the only thing done prior to 
   86:        dropping SUID should be opening the network state for
   87:        raw sockets.
   88:      */
   89:     init_net_state_privileged(&net_state);
   90:     if (drop_elevated_permissions()) {
   91:         error(EXIT_FAILURE, errno, "Unable to drop elevated permissions");
   92:     }
   93:     init_net_state(&net_state);
   94: 
   95:     init_command_buffer(&command_buffer, fileno(stdin));
   96: 
   97:     command_pipe_open = true;
   98: 
   99:     /*
  100:        Dispatch commands and respond to probe replies until the
  101:        command stream is closed.
  102:      */
  103:     while (true) {
  104:         /*  Ensure any responses are written before waiting  */
  105:         fflush(stdout);
  106:         wait_for_activity(&command_buffer, &net_state);
  107: 
  108:         /*
  109:            Receive replies first so that the timestamps are as
  110:            close to the response arrival time as possible.
  111:          */
  112:         receive_replies(&net_state);
  113: 
  114:         if (command_pipe_open) {
  115:             if (read_commands(&command_buffer)) {
  116:                 if (errno == EPIPE) {
  117:                     command_pipe_open = false;
  118:                 }
  119:             }
  120:         }
  121: 
  122:         check_probe_timeouts(&net_state);
  123: 
  124:         /*
  125:            Dispatch commands late so that the window between probe
  126:            departure and arriving replies is as small as possible.
  127:          */
  128:         dispatch_buffer_commands(&command_buffer, &net_state);
  129: 
  130:         /*
  131:            If the command pipe has been closed, exit after all
  132:            in-flight probes have reported their status.
  133:          */
  134:         if (!command_pipe_open) {
  135:             if (net_state.outstanding_probe_count == 0) {
  136:                 break;
  137:             }
  138:         }
  139:     }
  140: 
  141:     return 0;
  142: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>