int main(int argc, char *argv[]) { struct timespec ts; char *p; if (argc != 2) goto err; p = strtotimespec(argv[1], &ts); if (*p) goto err; while (nanosleep(&ts, &ts) == -1 && errno == EINTR) ; return 0; err: fprintf(stderr, "Usage: %s seconds[.fraction]\n", argv[0]); return 1; }
/* * Function: parse_options() * * Description: * This function parse the options * * Argument: * argc: the number of argument * argv: arguments * info_p: pointer to data of querier information * bg_p: pointer to the flag of working in backgrond * * Return value: * None */ void parse_options(int argc, char *argv[], struct igmp_info *info_p, int *bg_p) { int optc; /* option */ unsigned long opt_ul; /* option value in unsigned long */ double opt_d; /* option value in double */ uint8_t max_resp; /* Max Resp Code */ char *maddr; /* multicast address */ char *saddrs; /* comma separated array of source addresses */ max_resp = IGMP_MAX_HOST_REPORT_DELAY; maddr = NULL; saddrs = NULL; while ((optc = getopt(argc, argv, "I:m:s:r:t:i:obdh")) != EOF) { switch (optc) { case 'I': info_p->ifindex = if_nametoindex(optarg); if (info_p->ifindex == 0) { fprintf(stderr, "specified interface is incorrect\n"); usage(program_name, EXIT_FAILURE); } break; case 'm': maddr = strdup(optarg); if (maddr == NULL) fatal_error("strdup()"); break; case 's': saddrs = strdup(optarg); if (saddrs == NULL) fatal_error("strdup()"); break; case 'r': opt_ul=strtoul(optarg, NULL, 0); if (opt_ul > 255) { fprintf(stderr, "Max Resp Code should be less then 256\n"); usage(program_name, EXIT_FAILURE); } max_resp = opt_ul; break; case 't': opt_d = strtod(optarg, NULL); if (opt_d < 0.0) { fprintf(stderr, "Timeout should be positive value\n"); usage(program_name, EXIT_FAILURE); } info_p->timeout = opt_d; break; case 'i': if (strtotimespec(optarg, &info_p->interval)) { fprintf(stderr, "Interval is something wrong\n"); usage(program_name, EXIT_FAILURE); } break; case 'o': info_p->timeout = -1.0; break; case 'b': *bg_p = 1; break; case 'd': debug = 1; break; case 'h': usage(program_name, EXIT_SUCCESS); break; default: usage(program_name, EXIT_FAILURE); } } if (info_p->ifindex == 0) { fprintf(stderr, "specified interface seems incorrect\n"); usage(program_name, EXIT_FAILURE); } if ((info_p->query = create_query(max_resp, maddr, saddrs)) == NULL) usage(program_name, EXIT_FAILURE); if (maddr) free(maddr); if (saddrs) free(saddrs); }
/* * Function: parse_options() * * Description: * This function parse the options * * Argument: * argc: the number of argument * argv: arguments * info_p: pointer to data of icmp data to modify * bg_p: pointer to the flag of working in backgrond * * Return value: * None */ void parse_options(int argc, char *argv[], struct icmp6_info *info_p, int *bg_p) { int optc; /* option */ unsigned long opt_ul; /* option value in unsigned long */ double opt_d; /* option value in double */ struct in6_addr opt_addr; /* option value in struct in_addr */ struct sockaddr_ll opt_addr_ll; /* option value in struct sockaddr_ll */ char *ifname; /* interface name where datagrams go out */ int is_mld_query; /* set to non-zero if sending MLDv2 query */ char *mld_saddrs; /* comma separated array of source addresses */ uint16_t max_resp; /* Max Resp Code */ int is_specified_daddr_ll = 0; int is_specified_saddr = 0; int is_specified_daddr = 0; ifname = NULL; is_mld_query = 0; mld_saddrs = NULL; max_resp = MY_MLD_MAX_HOST_REPORT_DELAY; while ((optc = getopt(argc, argv, "I:S:M:D:t:w:obdhs:iLnvma:r:")) != EOF ) { switch (optc) { case 'I': if(if_nametoindex(optarg) == 0) { fprintf(stderr, "specified interface is incorrect\n"); usage(program_name, EXIT_FAILURE); } ifname = strdup(optarg); if (ifname == NULL) fatal_error("strdup() failed."); break; case 'S': if (inet_pton(AF_INET6, optarg, &opt_addr) <= 0) { fprintf(stderr, "Source address is wrong\n"); usage(program_name, EXIT_FAILURE); } info_p->saddr = opt_addr; is_specified_saddr = 1; break; case 'M': if (eth_pton(AF_INET6, optarg, &opt_addr_ll)) { fprintf(stderr, "Destination MAC address is wrong\n"); usage(program_name, EXIT_FAILURE); } info_p->daddr_ll = opt_addr_ll; is_specified_daddr_ll = 1; break; case 'D': if (inet_pton(AF_INET6, optarg, &opt_addr) <= 0) { fprintf(stderr, "Destination address is wrong\n"); usage(program_name, EXIT_FAILURE); } info_p->daddr = opt_addr; is_specified_daddr = 1; break; case 't': opt_d = strtod(optarg, NULL); if (opt_d < 0.0) { fprintf(stderr, "Timeout should be positive value\n"); usage(program_name, EXIT_FAILURE); } info_p->timeout = opt_d; break; case 'w': if (strtotimespec(optarg, &info_p->interval)) { fprintf(stderr, "Interval is something wrong\n"); usage(program_name, EXIT_FAILURE); } break; case 'o': info_p->timeout = -1.0; break; case 'b': *bg_p = 1; break; case 'd': debug = 1; break; case 'h': usage(program_name, EXIT_SUCCESS); break; /* Options for echo request */ case 's': opt_ul = strtoul(optarg, NULL, 0); if (opt_ul > ICMPV6_DATA_MAXSIZE) { fprintf(stderr, "Data size sholud be less than %d\n", ICMPV6_DATA_MAXSIZE + 1); usage(program_name, EXIT_FAILURE); } info_p->data_size = opt_ul; break; /* Options for fake */ case 'i': info_p->fake_flag |= FAKE_DADDR; break; case 'L': info_p->fake_flag |= FAKE_PLEN; break; case 'n': info_p->fake_flag |= FAKE_NXT; break; case 'v': info_p->fake_flag |= FAKE_VERSION; break; /* Options for MLDv2 query */ case 'm': is_mld_query = 1; break; case 'a': mld_saddrs = strdup(optarg); if (mld_saddrs == NULL) fatal_error("strdup()"); break; case 'r': opt_ul=strtoul(optarg, NULL, 0); if (opt_ul > 0xFFFF) { fprintf(stderr, "Max Resp Code should be less than 65536\n"); usage(program_name, EXIT_FAILURE); } max_resp = opt_ul; break; default: usage(program_name, EXIT_FAILURE); } } if (ifname == NULL) { fprintf(stderr, "Outgoing interface is not specified\n"); usage(program_name, EXIT_FAILURE); } specify_hw_addr(&info_p->saddr_ll, ifname); if (! is_specified_saddr) { fprintf(stderr, "Source IP address is not specified\n"); usage(program_name, EXIT_FAILURE); } if (is_mld_query) { /* MLDv2 query */ if (info_p->fake_flag) { fprintf(stderr, "It is not permitted to break MLDv2 query\n"); usage(program_name, EXIT_FAILURE); } if (! is_specified_daddr) info_p->daddr = in6addr_allnodes; calc_hd_mcastaddr(&info_p->daddr_ll, &info_p->daddr); if (create_mld_query(info_p, max_resp, mld_saddrs)) exit(EXIT_FAILURE); } else { /* echo request */ if (info_p->fake_flag) srand(getpid()); if (! is_specified_daddr_ll) { fprintf(stderr, "Destination MAC address is not specified\n"); usage(program_name, EXIT_FAILURE); } if (! is_specified_daddr) { fprintf(stderr, "Destination IP address is not specified\n"); usage(program_name, EXIT_FAILURE); } create_echo_request(info_p); } info_p->daddr_ll.sll_ifindex = if_nametoindex(ifname); }