1818 */
1919
2020#define _GNU_SOURCE
21+ #include <dirent.h>
2122#include <errno.h>
2223#include <fcntl.h>
2324#include <inttypes.h>
@@ -54,6 +55,7 @@ static int g_sockfd = 0;
5455static int g_exit = 0 ;
5556static int g_daemon = 0 ;
5657static int g_silent = 0 ;
58+ static int g_killproc = 0 ;
5759static int g_repeat = 3 ;
5860static uint32_t g_fwmark = 0x8000 ;
5961static uint32_t g_fwmask = 0 ;
@@ -71,6 +73,7 @@ static void print_usage(const char *name)
7173 " -d run as a daemon\n"
7274 " -h <hostname> hostname for obfuscation (required)\n"
7375 " -i <interface> network interface name (required)\n"
76+ " -k kill the running process\n"
7477 " -m <mark> fwmark for bypassing the queue\n"
7578 " -n <number> netfilter queue number\n"
7679 " -r <repeat> duplicate generated packets for <repeat> "
@@ -174,6 +177,76 @@ static int signal_setup(void)
174177}
175178
176179
180+ static int kill_running (int signal )
181+ {
182+ int res , matched , err ;
183+ ssize_t len ;
184+ DIR * procfs ;
185+ struct dirent * entry ;
186+ pid_t pid , self_pid ;
187+ char self_path [PATH_MAX ], proc_path [PATH_MAX ], exe_path [PATH_MAX ];
188+
189+ self_pid = getpid ();
190+
191+ len = readlink ("/proc/self/exe" , self_path , sizeof (self_path ));
192+ if (len < 0 || (size_t ) len >= sizeof (self_path )) {
193+ E ("ERROR: readlink(): /proc/self/exe: %s" , strerror (errno ));
194+ return -1 ;
195+ }
196+ self_path [len ] = 0 ;
197+
198+ procfs = opendir ("/proc" );
199+ if (!procfs ) {
200+ E ("ERROR: opendir(): /proc: %s" , strerror (errno ));
201+ return -1 ;
202+ }
203+
204+ matched = err = 0 ;
205+ while ((entry = readdir (procfs ))) {
206+ pid = strtoull (entry -> d_name , NULL , 0 );
207+ if (pid <= 1 || pid == self_pid ) {
208+ continue ;
209+ }
210+
211+ res = snprintf (exe_path , sizeof (exe_path ), "/proc/%s/exe" ,
212+ entry -> d_name );
213+ if (res < 0 || (size_t ) res >= sizeof (exe_path )) {
214+ continue ;
215+ }
216+
217+ len = readlink (exe_path , proc_path , sizeof (proc_path ));
218+ if (len < 0 || (size_t ) len >= sizeof (self_path )) {
219+ continue ;
220+ }
221+ proc_path [len ] = 0 ;
222+
223+ if (strcmp (self_path , proc_path ) == 0 ) {
224+ matched = 1 ;
225+
226+ if (signal ) {
227+ res = kill (pid , signal );
228+ if (res < 0 ) {
229+ E ("ERROR: kill(): %llu: %s" , pid , strerror (errno ));
230+ err = 1 ;
231+ }
232+ }
233+ }
234+ }
235+
236+ res = closedir (procfs );
237+ if (res < 0 ) {
238+ E ("ERROR: closedir(): %s" , strerror (errno ));
239+ err = 1 ;
240+ }
241+
242+ if (matched && !err ) {
243+ return 0 ;
244+ }
245+
246+ return -1 ;
247+ }
248+
249+
177250static int execute_command (char * * argv , int silent )
178251{
179252 int res , status , fd , i ;
@@ -714,7 +787,7 @@ int main(int argc, char *argv[])
714787 return EXIT_FAILURE ;
715788 }
716789
717- while ((opt = getopt (argc , argv , "dh:i:m :n:r:st:w:x:" )) != -1 ) {
790+ while ((opt = getopt (argc , argv , "dh:i:km :n:r:st:w:x:" )) != -1 ) {
718791 switch (opt ) {
719792 case 'd' :
720793 g_daemon = 1 ;
@@ -736,6 +809,9 @@ int main(int argc, char *argv[])
736809 return EXIT_FAILURE ;
737810 }
738811 break ;
812+ case 'k' :
813+ g_killproc = 1 ;
814+ break ;
739815 case 'm' :
740816 tmp = strtoull (optarg , NULL , 0 );
741817 if (!tmp || tmp > UINT32_MAX ) {
@@ -799,6 +875,11 @@ int main(int argc, char *argv[])
799875 }
800876 }
801877
878+ if (g_killproc ) {
879+ res = kill_running (SIGTERM );
880+ return res ? EXIT_FAILURE : EXIT_SUCCESS ;
881+ }
882+
802883 if (!g_fwmask ) {
803884 g_fwmask = g_fwmark ;
804885 } else if ((g_fwmark & g_fwmask ) != g_fwmark ) {
@@ -909,7 +990,13 @@ int main(int argc, char *argv[])
909990 if (!qh ) {
910991 switch (errno ) {
911992 case EPERM :
912- err_hint = " (Another process is running / Are you root?)" ;
993+ res = kill_running (0 );
994+ errno = EPERM ;
995+ if (res ) {
996+ err_hint = " (Another process is running / Are you root?)" ;
997+ } else {
998+ err_hint = " (Another process is running)" ;
999+ }
9131000 break ;
9141001 case EINVAL :
9151002 err_hint = " (Missing kernel module?)" ;
0 commit comments