Annotation of embedaddon/mtr/packet/packet.c, revision 1.1.1.1
1.1 misho 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
15: along with this program; if not, write to the Free Software
16: Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17: */
18:
19: #include "config.h"
20:
21: #include <errno.h>
22: #include <stdio.h>
23: #include <stdlib.h>
24: #include <string.h>
25: #include <unistd.h>
26:
27: #ifdef HAVE_LIBCAP
28: #include <sys/capability.h>
29: #endif
30:
31: #include "wait.h"
32:
33: /* Drop SUID privileges. To be used after accquiring raw sockets. */
34: static
35: int drop_elevated_permissions(
36: void)
37: {
38: #ifdef HAVE_LIBCAP
39: cap_t cap;
40: #endif
41:
42: /* Drop any suid permissions granted */
43: if (setgid(getgid()) || setuid(getuid())) {
44: return -1;
45: }
46:
47: if (geteuid() != getuid() || getegid() != getgid()) {
48: return -1;
49: }
50:
51: /*
52: Drop all process capabilities.
53: This will revoke anything granted by a commandline 'setcap'
54: */
55: #ifdef HAVE_LIBCAP
56: cap = cap_get_proc();
57: if (cap == NULL) {
58: return -1;
59: }
60: if (cap_clear(cap)) {
61: return -1;
62: }
63: if (cap_set_proc(cap)) {
64: return -1;
65: }
66: #endif
67:
68: return 0;
69: }
70:
71: int main(
72: int argc,
73: char **argv)
74: {
75: bool command_pipe_open;
76: struct command_buffer_t command_buffer;
77: struct net_state_t net_state;
78:
79: /*
80: To minimize security risk, the only thing done prior to
81: dropping SUID should be opening the network state for
82: raw sockets.
83: */
84: init_net_state_privileged(&net_state);
85: if (drop_elevated_permissions()) {
86: perror("Unable to drop elevated permissions");
87: exit(EXIT_FAILURE);
88: }
89: init_net_state(&net_state);
90:
91: init_command_buffer(&command_buffer, fileno(stdin));
92:
93: command_pipe_open = true;
94:
95: /*
96: Dispatch commands and respond to probe replies until the
97: command stream is closed.
98: */
99: while (true) {
100: /* Ensure any responses are written before waiting */
101: fflush(stdout);
102: wait_for_activity(&command_buffer, &net_state);
103:
104: /*
105: Receive replies first so that the timestamps are as
106: close to the response arrival time as possible.
107: */
108: receive_replies(&net_state);
109:
110: if (command_pipe_open) {
111: if (read_commands(&command_buffer)) {
112: if (errno == EPIPE) {
113: command_pipe_open = false;
114: }
115: }
116: }
117:
118: check_probe_timeouts(&net_state);
119:
120: /*
121: Dispatch commands late so that the window between probe
122: departure and arriving replies is as small as possible.
123: */
124: dispatch_buffer_commands(&command_buffer, &net_state);
125:
126: /*
127: If the command pipe has been closed, exit after all
128: in-flight probes have reported their status.
129: */
130: if (!command_pipe_open) {
131: if (net_state.outstanding_probe_count == 0) {
132: break;
133: }
134: }
135: }
136:
137: return 0;
138: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>