static int add_target(unsigned long ptr) { int err; struct target_info info; if ((err = copy_from_user(&info, (void *) ptr, sizeof(info))) < 0) return err; if (!(err = target_add(&info))) err = copy_to_user((void *) ptr, &info, sizeof(info)); return err; }
static int add_target(unsigned long ptr) { struct target_info info; int err; err = copy_from_user(&info, (void *) ptr, sizeof(info)); if (err) return -EFAULT; err = target_add(&info); if (err < 0) return err; err = copy_to_user((void *) ptr, &info, sizeof(info)); if (err) return -EFAULT; return 0; }
/* * Continiously probing multiple hosts using ICMP-ECHO. As packets are * received dots are printed on the screen. Hosts not responding before * next packet is due will get a questionmark in the display. The probing * stops when SIGINT is received. */ int main(int argc, char *argv[]) { char buf[BUFSIZ]; struct timeval tv; struct target *t; char *end; int i; int len; char ch; #ifdef DO_SOCK_RAW /* Open RAW-socket and drop root-privs */ fd4 = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); fd4errno = errno; fd6 = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); fd6errno = errno; if (setuid(getuid()) < 0) { perror("setuid"); exit(EX_OSERR); } #else /* !DO_SOCK_RAW */ fd4 = -1; fd4errno = EAFNOSUPPORT; fd6 = -1; fd6errno = EAFNOSUPPORT; #endif /* DO_SOCK_RAW */ /* Parse command line options */ while ((ch = getopt(argc, argv, "46ABCTVahc:i:w:")) != -1) { switch(ch) { case '4': v4_flag = 1; v6_flag = 0; break; case '6': v4_flag = 0; v6_flag = 1; break; case 'a': a_flag++; break; case 'A': A_flag++; break; case 'B': B_flag = 1; break; case 'C': C_flag = 1; break; case 'c': c_count = strtol(optarg, &end, 10); if (*optarg != '\0' && *end != '\0') usage("Invalid count"); break; case 'T': T_flag = 1; break; case 'i': i_interval = strtod(optarg, &end) * 1000; if (*optarg != '\0' && *end != '\0') usage("Invalid interval"); if (i_interval < 1000 && getuid() != 0) usage("Dangerous interval"); break; case 'w': w_width = strtol(optarg, &end, 10); if (*optarg != '\0' && *end != '\0') usage("Invalid width"); if (w_width < 0) usage("Invalid width"); break; case 'V': fprintf(stderr, "%s %s\n", "xping", version); return (0); case 'h': usage(NULL); /* NOTREACHED */ default: usage(NULL); /* NOTREACHED */ } } argc -= optind; argv += optind; tv_interval.tv_sec = i_interval / 1000; tv_interval.tv_usec = i_interval % 1000 * 1000; /* Prepare event system and inbound socket */ ev_base = event_base_new(); dns = evdns_base_new(ev_base, 1); probe_setup(); /* Read targets from program arguments and/or stdin. */ list = NULL; for (i=0; i<argc; i++) { if (target_add(argv[i]) < 0) { return 1; } } if (!isatty(STDIN_FILENO) || argc < 1) { while(fgets(buf, sizeof(buf), stdin) != NULL) { if ((end = strchr(buf, '#')) != NULL) *end = '\0'; for (len = strlen(buf) - 1; len > 0; len--) { if (strchr(" \t\n", buf[len]) == NULL) break; buf[len] = '\0'; } if (buf[0] == '#' || len < 1) continue; if (target_add(buf) < 0) { perror("malloc"); return 1; } } } if (!isatty(STDOUT_FILENO)) { ui_init = report_init; ui_update = report_update; ui_cleanup = report_cleanup; } if (list == NULL) { usage("no arguments"); } /* Initial scheduling with increasing delay, distributes * transmissions across the interval and gives a cascading effect. */ tv.tv_sec = 0; tv.tv_usec = 0; DL_FOREACH(list, t) { t->ev_write = event_new(ev_base, -1, 0, target_probe_sched, t); event_add(t->ev_write, &tv); tv.tv_usec += 100*1000; /* target spacing: 100ms */ tv.tv_sec += (tv.tv_usec >= 1000000 ? 1 : 0); tv.tv_usec -= (tv.tv_usec >= 1000000 ? 1000000 : 0); }