예제 #1
0
파일: camd.c 프로젝트: joolzg/tsdecrypt
static int camd_recv_cw(struct ts *ts) {
	struct camd *c = &ts->camd;
	struct timeval tv1, tv2, last_ts_keyset;
	uint16_t ca_id = 0;
	uint16_t idx = 0;
	int ret;

	gettimeofday(&tv1, NULL);
	ret = c->ops.get_cw(c, &ca_id, &idx, c->key->cw);
	gettimeofday(&tv2, NULL);

	if (ret <= 0) {
		if (ret == -1) { // Fatal error it is better to reconnect to server.
			ts_LOGf("ERR | No code word has been received (ret = %d)\n", ret);
			c->ops.reconnect(c);
		}
		c->ecm_recv_errors++;
		if (c->ecm_recv_errors >= ECM_RECV_ERRORS_LIMIT) {
			c->key->is_valid_cw = 0;
			memset(c->key->cw, 0, 16); // Invalid CW
		}
		usleep(10000);
		return 0;
	}

	char cw_dump[16 * 6];
	ts_hex_dump_buf(cw_dump, 16 * 6, c->key->cw, 16, 0);

	int valid_cw = memcmp(c->key->cw, invalid_cw, 16) != 0;
	if (!c->key->is_valid_cw && valid_cw) {
		ts_LOGf("CW  | OK: Valid code word was received.\n");
		notify(ts, "CODE_WORD_OK", "Valid code word was received.");
	}
	c->key->is_valid_cw = valid_cw;

	// At first ts_keyset is not initialized
	last_ts_keyset = c->key->ts_keyset;
	if (c->key->is_valid_cw)
		camd_set_cw(ts, c->key->cw, 1);

	if (ts->ecm_cw_log) {
		ts_LOGf("CW  | SID 0x%04x CAID: 0x%04x CW_recv: %5llu ms LastKey: %5llu ms Data: %s\n",
			ts->service_id,
			ca_id,
			timeval_diff_msec(&tv1, &tv2),
			timeval_diff_msec(&last_ts_keyset, &tv2),
			cw_dump );
	}

	return 1;
}
예제 #2
0
/*
 * get_timeout
 * returns the amount of time that select should block for before returning
 * whether some packets have arrived or not
 */
static int get_timeout(struct timeval *tv)
{
  struct timeval  temp;
  int64_t         min_diff = 1000, temp_diff;

  if(tv == NULL)
    {
      return 0;
    }

  bzero(&temp, sizeof(temp));
  bzero(&tz,   sizeof(tz));
  if(gettimeofday(&temp, &tz) != 0)
    {
      printerror(errno, strerror, "could not gettimeofday");
      return 0;
    }

  if(wait_between > 0)
    {
      temp_diff = timeval_diff_msec(&wait_between_tv, &temp);
      if(temp_diff >= 0 && temp_diff < min_diff) min_diff = temp_diff;
    }

  tv->tv_sec  = 0;
  tv->tv_usec = 0;
  timeval_add(tv, min_diff);

  return 1;
}
예제 #3
0
void process_packets(struct ts *ts, uint8_t *ts_packet, ssize_t readen) {
	struct timeval now;
	struct packet *packet = ts->current_packet;

	if (packet->data_len + readen < PACKET_MAX_LENGTH) {
		// Add data to buffer
		memcpy(packet->data + packet->data_len, ts_packet, readen);
		packet->data_len += readen;
	} else {
		// Too much data, add to queue
		p_dbg1("*** Reached buffer end (%zd + %zd > %d)\n", packet->data_len + readen, readen, PACKET_MAX_LENGTH);
		packet = add_to_queue(ts);
	}

	if (!packet->ts.tv_sec)
		gettimeofday(&packet->ts, NULL);

	gettimeofday(&now, NULL);
	unsigned long long diff = timeval_diff_msec(&packet->ts, &now);
	if (diff > PACKET_MAX_TIME) {
		// Too much time have passed, add to queue
		p_dbg1("+++ Reached time limit (%llu > %d)\n", diff, PACKET_MAX_TIME);
		add_to_queue(ts);
	}
}
void
poll_process_rss (struct poll_state *ps)
{
    struct task_basic_info ti;
    int ret;

    ++ps->num_polls;
    ret = get_task_info(ps, &ti);
    if (ret != 0) {
        if ((ret == 2) && (ps->num_polls >= 2)) {
            // Then guess that this is not because of lack of
            // permissions, because we have successfully made the call
            // before.  Guess that this is because the child process
            // has exited already.  Unfortunately I do not see a good
            // way to determine that this has happened other than by
            // guessing, but there is probably a Mach way to do it
            // with some API call.

            // Record the time this has happened, so we can later tell
            // if it is close to the time the child process exits.
            // Also indicate that we should disable the timer now.
            ps->task_info_errored = 1;
            ret = gettimeofday(&(ps->task_info_error_time), NULL);
            // TBD: check ret?
            return;
        }
        run_as_superuser_msg(global_prog_name);
        exit(1);
    }
    natural_t rss_bytes = ti.resident_size;
    if (ps->verbose_poll) {
        double rss_mbytes = (double) rss_bytes / (1024.0 * 1024.0);
        printf("rss (mb)=%.1f\n", rss_mbytes);
    }
    struct timeval this_poll_time;
    ret = gettimeofday(&this_poll_time, NULL);
    if (ps->first_poll || (rss_bytes > ps->max_rss_bytes)) {
        ps->max_rss_bytes = rss_bytes;
        memcpy(&(ps->poll_time_when_maxrss_first_seen),
               &this_poll_time, sizeof(struct timeval));
    }
    if (!ps->first_poll) {
        int64 delta = timeval_diff_msec(&(ps->prev_poll_time),
                                        &this_poll_time);
        if (delta < ps->consecutive_poll_separation_min_msec) {
            ps->consecutive_poll_separation_min_msec = delta;
        }
        if (delta > ps->consecutive_poll_separation_max_msec) {
            ps->consecutive_poll_separation_max_msec = delta;
        }
    }
    ps->first_poll = 0;
    memcpy(&(ps->prev_poll_time), &this_poll_time, sizeof(struct timeval));
}
예제 #5
0
static void
log_poll_interval(long long int last_wakeup)
{
    long long int interval = time_msec() - last_wakeup;

    if (interval >= 1000 && !is_warped(&monotonic_clock)) {
        const struct rusage *last_rusage = get_recent_rusage();
        struct rusage rusage;

        getrusage(RUSAGE_SELF, &rusage);
        VLOG_WARN("Unreasonably long %lldms poll interval"
                  " (%lldms user, %lldms system)",
                  interval,
                  timeval_diff_msec(&rusage.ru_utime,
                                    &last_rusage->ru_utime),
                  timeval_diff_msec(&rusage.ru_stime,
                                    &last_rusage->ru_stime));
        if (rusage.ru_minflt > last_rusage->ru_minflt
            || rusage.ru_majflt > last_rusage->ru_majflt) {
            VLOG_WARN("faults: %ld minor, %ld major",
                      rusage.ru_minflt - last_rusage->ru_minflt,
                      rusage.ru_majflt - last_rusage->ru_majflt);
        }
        if (rusage.ru_inblock > last_rusage->ru_inblock
            || rusage.ru_oublock > last_rusage->ru_oublock) {
            VLOG_WARN("disk: %ld reads, %ld writes",
                      rusage.ru_inblock - last_rusage->ru_inblock,
                      rusage.ru_oublock - last_rusage->ru_oublock);
        }
        if (rusage.ru_nvcsw > last_rusage->ru_nvcsw
            || rusage.ru_nivcsw > last_rusage->ru_nivcsw) {
            VLOG_WARN("context switches: %ld voluntary, %ld involuntary",
                      rusage.ru_nvcsw - last_rusage->ru_nvcsw,
                      rusage.ru_nivcsw - last_rusage->ru_nivcsw);
        }
        coverage_log();
    }
}
예제 #6
0
static int time_to_send_request()
{
  struct timeval tv;
  gettimeofday(&tv, &tz);

  if(sent_all_requests == 1)
    {
      return 0;
    }

  if(wait_between == 0)
    {
      return 1;
    }

  if(timeval_diff_msec(&wait_between_tv, &tv) > 0)
    {
      return 0;
    }

  return 1;
}
예제 #7
0
파일: hostmon.c 프로젝트: rogerhu/dd-wrt
void hostmon(time_t facilitytime, char *ifptr)
{
	int logging = options.logging;
	struct ethtab table;
	struct ethtabent *entry;

	char scratch_saddr[ETH_ALEN];
	char scratch_daddr[ETH_ALEN];
	unsigned int idx = 1;
	int is_ip;
	int ch;

	char *ifname = ifptr;

	struct timeval tv;
	struct timeval tv_rate;
	time_t now = 0;
	time_t statbegin = 0;
	time_t startlog = 0;
	struct timeval updtime;

	struct eth_desc *list = NULL;

	FILE *logfile = NULL;

	int pkt_result;

	WINDOW *sortwin;
	PANEL *sortpanel;
	int keymode = 0;

	int fd;

	if (ifptr && !dev_up(ifptr)) {
		err_iface_down();
		return;
	}

	LIST_HEAD(promisc);
	if (options.promisc) {
		promisc_init(&promisc, ifptr);
		promisc_set_list(&promisc);
	}

	hostmonhelp();

	initethtab(&table);

	/* Ethernet description list */
	struct eth_desc *elist = load_eth_desc(ARPHRD_ETHER);

	/* FDDI description list */
	struct eth_desc *flist = load_eth_desc(ARPHRD_FDDI);

	if (logging) {
		if (strcmp(current_logfile, "") == 0) {
			strncpy(current_logfile,
				gen_instance_logname(LANLOG, getpid()), 80);

			if (!daemonized)
				input_logfile(current_logfile, &logging);
		}
	}

	if (logging) {
		opentlog(&logfile, current_logfile);

		if (logfile == NULL)
			logging = 0;
	}
	if (logging) {
		signal(SIGUSR1, rotate_lanlog);

		rotate_flag = 0;
		writelog(logging, logfile,
			 "******** LAN traffic monitor started ********");
	}

	leaveok(table.tabwin, TRUE);

	fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
	if(fd == -1) {
		write_error("Unable to obtain monitoring socket");
		goto err;
	}
	if(ifptr && dev_bind_ifname(fd, ifptr) == -1) {
		write_error("Unable to bind interface on the socket");
		goto err_close;
	}

	exitloop = 0;
	gettimeofday(&tv, NULL);
	tv_rate = tv;
	updtime = tv;
	statbegin = startlog = tv.tv_sec;

	PACKET_INIT(pkt);

	do {
		gettimeofday(&tv, NULL);
		now = tv.tv_sec;

		unsigned long msecs = timeval_diff_msec(&tv, &tv_rate);
		if (msecs >= 1000) {
			printelapsedtime(statbegin, now, LINES - 3, 15,
					 table.borderwin);
			updateethrates(&table, msecs, idx);
			tv_rate = tv;
		}
		if (logging) {
			check_rotate_flag(&logfile);
			if ((now - startlog) >= options.logspan) {
				writeethlog(table.head, now - statbegin,
					    logfile);
				startlog = now;
			}
		}
		if (screen_update_needed(&tv, &updtime)) {
			update_panels();
			doupdate();

			updtime = tv;
		}

		if ((facilitytime != 0)
		    && (((now - statbegin) / 60) >= facilitytime))
			exitloop = 1;

		if (packet_get(fd, &pkt, &ch, table.tabwin) == -1) {
			write_error("Packet receive failed");
			exitloop = 1;
			break;
		}

		if (ch != ERR) {
			if (keymode == 0) {
				switch (ch) {
				case KEY_UP:
					scrollethwin(&table, SCROLLDOWN, &idx);
					break;
				case KEY_DOWN:
					scrollethwin(&table, SCROLLUP, &idx);
					break;
				case KEY_PPAGE:
				case '-':
					pageethwin(&table, SCROLLDOWN, &idx);
					break;
				case KEY_NPAGE:
				case ' ':
					pageethwin(&table, SCROLLUP, &idx);
					break;
				case 12:
				case 'l':
				case 'L':
					tx_refresh_screen();
					break;
				case 's':
				case 'S':
					show_hostsort_keywin(&sortwin,
							     &sortpanel);
					keymode = 1;
					break;
				case 'q':
				case 'Q':
				case 'x':
				case 'X':
				case 27:
				case 24:
					exitloop = 1;
				}
			} else if (keymode == 1) {
				del_panel(sortpanel);
				delwin(sortwin);
				sort_hosttab(&table, &idx, ch);
				keymode = 0;
			}
		}

		if (pkt.pkt_len <= 0)
			continue;

		char ifnamebuf[IFNAMSIZ];

		pkt_result =
			packet_process(&pkt, NULL, NULL, NULL,
				       MATCH_OPPOSITE_USECONFIG,
				       0);

		if (pkt_result != PACKET_OK)
			continue;

		if (!ifptr) {
			/* we're capturing on "All interfaces", */
			/* so get the name of the interface */
			/* of this packet */
			int r = dev_get_ifname(pkt.pkt_ifindex, ifnamebuf);
			if (r != 0) {
				write_error("Unable to get interface name");
				break;	/* can't get interface name, get out! */
			}
			ifname = ifnamebuf;
		}

		/* get HW addresses */
		switch (pkt.pkt_hatype) {
		case ARPHRD_ETHER: {
			memcpy(scratch_saddr, pkt.ethhdr->h_source, ETH_ALEN);
			memcpy(scratch_daddr, pkt.ethhdr->h_dest, ETH_ALEN);
			list = elist;
			break; }
		case ARPHRD_FDDI: {
			memcpy(scratch_saddr, pkt.fddihdr->saddr, FDDI_K_ALEN);
			memcpy(scratch_daddr, pkt.fddihdr->daddr, FDDI_K_ALEN);
			list = flist;
			break; }
		default:
			/* unknown link protocol */
			continue;
		}

		switch(pkt.pkt_protocol) {
		case ETH_P_IP:
		case ETH_P_IPV6:
			is_ip = 1;
			break;
		default:
			is_ip = 0;
			break;
		}

		/* Check source address entry */
		entry = in_ethtable(&table, pkt.pkt_hatype,
				    scratch_saddr);

		if (!entry)
			entry = addethentry(&table, pkt.pkt_hatype,
					    ifname, scratch_saddr, list);

		if (entry != NULL) {
			updateethent(entry, pkt.pkt_len, is_ip, 1);
			if (!entry->prev_entry->un.desc.printed)
				printethent(&table, entry->prev_entry,
					    idx);

			printethent(&table, entry, idx);
		}

		/* Check destination address entry */
		entry = in_ethtable(&table, pkt.pkt_hatype,
				    scratch_daddr);
		if (!entry)
			entry = addethentry(&table, pkt.pkt_hatype,
					    ifname, scratch_daddr, list);

		if (entry != NULL) {
			updateethent(entry, pkt.pkt_len, is_ip, 0);
			if (!entry->prev_entry->un.desc.printed)
				printethent(&table, entry->prev_entry,
					    idx);

			printethent(&table, entry, idx);
		}
	} while (!exitloop);

err_close:
	close(fd);

err:
	if (options.promisc) {
		promisc_restore_list(&promisc);
		promisc_destroy(&promisc);
	}

	if (logging) {
		signal(SIGUSR1, SIG_DFL);
		writeethlog(table.head, time(NULL) - statbegin, logfile);
		writelog(logging, logfile,
			 "******** LAN traffic monitor stopped ********");
		fclose(logfile);
	}


	del_panel(table.tabpanel);
	delwin(table.tabwin);
	del_panel(table.borderpanel);
	delwin(table.borderwin);
	update_panels();
	doupdate();
	destroyethtab(&table);

	free_eth_desc(elist);
	free_eth_desc(flist);

	strcpy(current_logfile, "");
}
예제 #8
0
파일: detstats.c 프로젝트: rogerhu/dd-wrt
/*
 * The detailed interface statistics function
 */
void detstats(char *iface, time_t facilitytime)
{
	int logging = options.logging;

	WINDOW *statwin;
	PANEL *statpanel;

	int pkt_result = 0;

	FILE *logfile = NULL;

	unsigned int iplen = 0;

	struct ifcounts ifcounts;

	int ch;

	struct timeval tv;
	struct timeval start_tv;
	struct timeval updtime;
	time_t starttime;
	time_t now;
	time_t statbegin;
	time_t startlog;

	struct proto_counter span;

	struct rate rate;
	struct rate rate_in;
	struct rate rate_out;
	unsigned long peakactivity = 0;
	unsigned long peakactivity_in = 0;
	unsigned long peakactivity_out = 0;

	struct rate pps_rate;
	struct rate pps_rate_in;
	struct rate pps_rate_out;
	unsigned long peakpps = 0;
	unsigned long peakpps_in = 0;
	unsigned long peakpps_out = 0;

	int fd;

	if (!dev_up(iface)) {
		err_iface_down();
		return;
	}

	LIST_HEAD(promisc);
	if (options.promisc) {
		promisc_init(&promisc, iface);
		promisc_set_list(&promisc);
	}

	move(LINES - 1, 1);
	stdexitkeyhelp();
	statwin = newwin(LINES - 2, COLS, 1, 0);
	statpanel = new_panel(statwin);
	tx_stdwinset(statwin);
	wtimeout(statwin, -1);
	wattrset(statwin, BOXATTR);
	tx_colorwin(statwin);
	tx_box(statwin, ACS_VLINE, ACS_HLINE);
	wmove(statwin, 0, 1);
	wprintw(statwin, " Statistics for %s ", iface);
	wattrset(statwin, STDATTR);
	update_panels();
	doupdate();

	memset(&ifcounts, 0, sizeof(struct ifcounts));

	if (logging) {
		if (strcmp(current_logfile, "") == 0) {
			snprintf(current_logfile, 64, "%s-%s.log", DSTATLOG,
				 iface);

			if (!daemonized)
				input_logfile(current_logfile, &logging);
		}
	}

	if (logging) {
		opentlog(&logfile, current_logfile);

		if (logfile == NULL)
			logging = 0;
	}
	if (logging) {
		signal(SIGUSR1, rotate_dstat_log);

		rotate_flag = 0;
		writelog(logging, logfile,
			 "******** Detailed interface statistics started ********");
	}

	printdetlabels(statwin);
	printdetails(&ifcounts, statwin);
	update_panels();
	doupdate();

	memset(&span, 0, sizeof(span));
	rate_alloc(&rate, 5);
	rate_alloc(&rate_in, 5);
	rate_alloc(&rate_out, 5);

	rate_alloc(&pps_rate, 5);
	rate_alloc(&pps_rate_in, 5);
	rate_alloc(&pps_rate_out, 5);

	gettimeofday(&tv, NULL);
	start_tv = tv;
	updtime = tv;
	starttime = startlog = statbegin = tv.tv_sec;

	leaveok(statwin, TRUE);

	fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
	if(fd == -1) {
		write_error("Unable to obtain monitoring socket");
		goto err;
	}
	if(dev_bind_ifname(fd, iface) == -1) {
		write_error("Unable to bind interface on the socket");
		goto err_close;
	}

	exitloop = 0;

	PACKET_INIT(pkt);

	/*
	 * Data-gathering loop
	 */

	while (!exitloop) {
		gettimeofday(&tv, NULL);
		now = tv.tv_sec;

		if ((now - starttime) >= 1) {
			char buf[64];
			unsigned long activity, activity_in, activity_out;
			unsigned long pps, pps_in, pps_out;
			unsigned long msecs;

			wattrset(statwin, BOXATTR);
			printelapsedtime(statbegin, now, LINES - 3, 1, statwin);

			msecs = timeval_diff_msec(&tv, &start_tv);

			rate_add_rate(&rate, span.proto_total.pc_bytes, msecs);
			activity = rate_get_average(&rate);
			rate_add_rate(&rate_in, span.proto_in.pc_bytes, msecs);
			activity_in = rate_get_average(&rate_in);
			rate_add_rate(&rate_out, span.proto_out.pc_bytes, msecs);
			activity_out = rate_get_average(&rate_out);

			rate_add_rate(&pps_rate, span.proto_total.pc_packets, msecs);
			pps = rate_get_average(&pps_rate);
			rate_add_rate(&pps_rate_in, span.proto_in.pc_packets, msecs);
			pps_in = rate_get_average(&pps_rate_in);
			rate_add_rate(&pps_rate_out, span.proto_out.pc_packets, msecs);
			pps_out = rate_get_average(&pps_rate_out);

			memset(&span, 0, sizeof(span));
			starttime = now;
			start_tv = tv;

			wattrset(statwin, HIGHATTR);
			rate_print(activity, buf, sizeof(buf));
			mvwprintw(statwin, 14, 19, "%s", buf);
			rate_print_pps(pps, buf, sizeof(buf));
			mvwprintw(statwin, 15, 19, "%s", buf);
			rate_print(activity_in, buf, sizeof(buf));
			mvwprintw(statwin, 17, 19, "%s", buf);
			rate_print_pps(pps_in, buf, sizeof(buf));
			mvwprintw(statwin, 18, 19, "%s", buf);
			rate_print(activity_out, buf, sizeof(buf));
			mvwprintw(statwin, 20, 19, "%s", buf);
			rate_print_pps(pps_out, buf, sizeof(buf));
			mvwprintw(statwin, 21, 19, "%s", buf);

			if (activity > peakactivity)
				peakactivity = activity;

			if (activity_in > peakactivity_in)
				peakactivity_in = activity_in;

			if (activity_out > peakactivity_out)
				peakactivity_out = activity_out;

			if (pps > peakpps)
				peakpps = pps;

			if (pps_in > peakpps_in)
				peakpps_in = pps_in;

			if (pps_out > peakpps_out)
				peakpps_out = pps_out;
		}
		if (logging) {
			check_rotate_flag(&logfile);
			if ((now - startlog) >= options.logspan) {
				writedstatlog(iface,
					      peakactivity, peakpps,
					      peakactivity_in, peakpps_in,
					      peakactivity_out, peakpps_out,
					      &ifcounts, time(NULL) - statbegin,
					      logfile);

				startlog = now;
			}
		}

		if (screen_update_needed(&tv, &updtime)) {
			printdetails(&ifcounts, statwin);
			update_panels();
			doupdate();

			updtime = tv;
		}

		if ((facilitytime != 0)
		    && (((now - statbegin) / 60) >= facilitytime))
			exitloop = 1;

		if (packet_get(fd, &pkt, &ch, statwin) == -1) {
			write_error("Packet receive failed");
			exitloop = 1;
			break;
		}

		switch (ch) {
		case ERR:
			/* no key ready, do nothing */
			break;
		case 12:
		case 'l':
		case 'L':
			tx_refresh_screen();
			break;

		case 'Q':
		case 'q':
		case 'X':
		case 'x':
		case 24:
		case 27:
			exitloop = 1;
			break;
		}
		if (pkt.pkt_len <= 0)
			continue;

		int outgoing;

		pkt_result =
			packet_process(&pkt, NULL, NULL, NULL,
				       MATCH_OPPOSITE_USECONFIG,
				       options.v6inv4asv6);

		if (pkt_result != PACKET_OK
		    && pkt_result != MORE_FRAGMENTS)
			continue;

		outgoing = (pkt.pkt_pkttype == PACKET_OUTGOING);
		update_proto_counter(&ifcounts.total, outgoing, pkt.pkt_len);
		if (pkt.pkt_pkttype == PACKET_BROADCAST) {
			update_pkt_counter(&ifcounts.bcast, pkt.pkt_len);
		}

		update_proto_counter(&span, outgoing, pkt.pkt_len);

		/* account network layer protocol */
		switch(pkt.pkt_protocol) {
		case ETH_P_IP:
			if (pkt_result == CHECKSUM_ERROR) {
				update_pkt_counter(&ifcounts.bad, pkt.pkt_len);
				continue;
			}

			iplen = ntohs(pkt.iphdr->tot_len);

			update_proto_counter(&ifcounts.ipv4, outgoing, iplen);
			break;
		case ETH_P_IPV6:
			iplen = ntohs(pkt.ip6_hdr->ip6_plen) + 40;

			update_proto_counter(&ifcounts.ipv6, outgoing, iplen);
			break;
		default:
			update_proto_counter(&ifcounts.nonip, outgoing, iplen);
			continue;
		}

		__u8 ip_protocol = pkt_ip_protocol(&pkt);

		/* account transport layer protocol */
		switch (ip_protocol) {
		case IPPROTO_TCP:
			update_proto_counter(&ifcounts.tcp, outgoing, iplen);
			break;
		case IPPROTO_UDP:
			update_proto_counter(&ifcounts.udp, outgoing, iplen);
			break;
		case IPPROTO_ICMP:
		case IPPROTO_ICMPV6:
			update_proto_counter(&ifcounts.icmp, outgoing, iplen);
			break;
		default:
			update_proto_counter(&ifcounts.other, outgoing, iplen);
			break;
		}
	}

err_close:
	close(fd);

err:
	rate_destroy(&pps_rate_out);
	rate_destroy(&pps_rate_in);
	rate_destroy(&pps_rate);

	rate_destroy(&rate_out);
	rate_destroy(&rate_in);
	rate_destroy(&rate);

	if (options.promisc) {
		promisc_restore_list(&promisc);
		promisc_destroy(&promisc);
	}

	if (logging) {
		signal(SIGUSR1, SIG_DFL);
		writedstatlog(iface,
			      peakactivity, peakpps, peakactivity_in,
			      peakpps_in, peakactivity_out, peakpps_out,
			      &ifcounts, time(NULL) - statbegin,
			      logfile);
		writelog(logging, logfile,
			 "******** Detailed interface statistics stopped ********");
		fclose(logfile);
	}

	del_panel(statpanel);
	delwin(statwin);
	strcpy(current_logfile, "");
	pkt_cleanup();
	update_panels();
	doupdate();
}
int
main (int argc, char **argv, char **envp)
{
    global_prog_name = argv[0];
    if (argc == 1) {
        usage(global_prog_name);
        exit(1);
    }

    // Determine which version of OS X we are running on.
    int major_version_num;
    int minor_version_num;
    int subminor_version_num;
    get_macosx_version(&major_version_num, &minor_version_num,
                       &subminor_version_num);
    struct poll_state ps;
    ps.use_polling = 0;
    if (major_version_num >= 10) {
        // Mac OS X 10.5.* and earlier return a number that appears
        // correct from the ru_maxrss field of getrusage(), also
        // filled in by wait4().

        // Mac OS X 10.6.* always returns 0 for ru_maxrss, so we must
        // use a different method to measure it.
        ps.use_polling = 1;
    }

    char **child_argv = (char **) malloc((unsigned) argc * sizeof(char *));
    int i;
    for (i = 1; i < argc; i++) {
        child_argv[i-1] = argv[i];
    }
    child_argv[argc-1] = NULL;
    // char **p;
    // for (p = child_argv; *p != NULL; p++) {
    //     fprintf(stderr, " p[%d]='%s'", p-child_argv, *p);
    // }
    // fprintf(stderr, "\n");

    struct timeval start_time;
    struct timeval end_time;
    unsigned int num_cpus = get_num_cpus();
    cpu_usage *total_cpu_stats_start = malloc_cpu_stats(1);
    cpu_usage *per_cpu_stats_start = malloc_cpu_stats(num_cpus);
    cpu_usage *total_cpu_stats_end = malloc_cpu_stats(1);
    cpu_usage *per_cpu_stats_end = malloc_cpu_stats(num_cpus);

    get_cpu_usage(num_cpus, per_cpu_stats_start, total_cpu_stats_start);
    int ret = gettimeofday(&start_time, NULL);
    // tbd: check ret

    pid_t pid = fork();
    if (pid == -1) {
        fprintf(stderr, "Error return status -1 while attempting"
                " to call fork().  errno=%d\n", errno);
        perror(global_prog_name);
        exit(3);
    } else if (pid == 0) {

        // We are the child process

        // Set the uid to the original uid of the process that invoked
        // the timemem-darwin process, so that the command being
        // measured is run with that user's priviliges, not with root
        // privileges.
        int original_uid = getuid();
        int ret = setuid(original_uid);
        if (ret != 0) {
            fprintf(stderr, "Error return status %d while attempting"
                    " to set uid to %d.  errno=%d\n", ret, original_uid,
                    errno);
            perror(global_prog_name);
            exit(4);
        }

        ret = execvp(child_argv[0], child_argv);
        // Normally the call above will not return.
        fprintf(stderr, "Error return status %d while attempting"
                " to call execvp().  errno=%d\n", ret, errno);
        perror(global_prog_name);
        exit(2);

    }

    // We are the parent process.

    // We want to wait until the child process finishes, but we also
    // want to periodically poll the child process's resident set size
    // (memory usage).  On OS X 10.5.8 and earlier, simply using
    // wait4() for the child to finish would fill in the rusage struct
    // with the maximum resident set size, but this value is always
    // filled in with 0 in OS X 10.6, hence the use of polling.

    // We implement the polling by calling setitimer() so that we are
    // sent a SIGALRM signal every 100 msec.  This should cause
    // wait4() to return early.  We handle the signal, and then call
    // wait4() again.

    // Read the current maximum resident set size once before starting
    // the timer, because the most likely reason for it to fail is
    // that we are not running with root privileges.
    if (ps.use_polling) {
        if (init_polling_process_rss(pid, &ps) != 0) {
            run_as_superuser_msg(global_prog_name);
            exit(1);
        }
        poll_process_rss(&ps);
        
        // Set up the SIGALRM signal handler.
        global_sigalrm_handled = 0;
        enable_handling_sigalrm();
        
        // Set timer to send us a SIGALRM signal every 100 msec.
        int timer_period_msec = 100;
        enable_timer(timer_period_msec);
    }

    //int wait_opts = WNOHANG;
    int wait_opts = 0;
    int wait_status;
    int wait4_ret;
    struct rusage r;
    while (1) {
        wait4_ret = wait4(pid, &wait_status, wait_opts, &r);
        if (wait4_ret != -1) {
            break;
        }
        if ((errno == EINTR) && ps.use_polling) {
            // Most likely the SIGALRM timer signal was handled.  If
            // so, poll the child process's memory use once.  The
            // timer should automatically signal again periodically
            // without having to reset it.
            if (global_sigalrm_handled) {
                poll_process_rss(&ps);
                global_sigalrm_handled = 0;
                if (ps.task_info_errored) {
                    disable_timer();
                    ignore_sigalrm();
                }
            }
            // Go around and call wait4() again.
        } else {
            fprintf(stderr, "wait4() returned %d.  errno=%d\n",
                    wait4_ret, errno);
            perror(global_prog_name);
            exit(5);
        }
    }

    // We may not use end_time if there are errors we haven't checked
    // for yet from wait4(), but it is more accurate to call this as
    // soon after wait4() returns as we can.  It is out of the loop
    // above to avoid the overhead of calling it on every poll time.
    if (debug) {
        fprintf(stderr, "About to call gettimeofday()\n");
    }
    ret = gettimeofday(&end_time, NULL);
    // tbd: check ret
    get_cpu_usage(num_cpus, per_cpu_stats_end, total_cpu_stats_end);
    
    if (wait4_ret != pid) {
        fprintf(stderr, "wait4() returned pid=%d.  Expected pid"
                " %d of child process.  Try again.\n", wait4_ret, pid);
        fprintf(stderr, "wait4 r.ru_maxrss=%ld\n", r.ru_maxrss);
        exit(7);
    }
    ps.wait4_returned_normally = 1;
    if (debug) {
        fprintf(stderr, "wait4() returned pid=%d of child process."
                "  Done!\n", pid);
    }
    
    if (ps.use_polling) {
        // Disable the timer.  Ignore SIGALRM, too, just in case one
        // more happens.
        if (debug) {
            fprintf(stderr, "About to disable the timer\n");
        }
        disable_timer();
        if (debug) {
            fprintf(stderr, "About to ignore SIGALRM\n");
        }
        ignore_sigalrm();
    }

    // Elapsed time
    int elapsed_msec = timeval_diff_msec(&start_time, &end_time);
    fprintf(stderr, "real %9d.%03d\n", (elapsed_msec / 1000),
            (elapsed_msec % 1000));

    // User, sys times
    fprintf(stderr, "user %9ld.%03d\n", r.ru_utime.tv_sec,
            r.ru_utime.tv_usec / 1000);
    fprintf(stderr, "sys  %9ld.%03d\n", r.ru_stime.tv_sec,
            r.ru_stime.tv_usec / 1000);
    
    // Maximum resident set size
    
    if (! ps.use_polling) {
        // At least on the Intel Core 2 Duo Mac OS X 10.5.8 machine on
        // which I first tested this code, it seemed to give a value
        // of up to 2^31-4096 bytes correctly, but if it went a little
        // bit over that, the fprintf statement showed it as 0, not
        // 2^31 bytes.  For now, I'll do a special check for 0 and
        // print out what I believe to be the correct value.
        
        // One way to test this on that machine is as follows.  The
        // first command below prints 2^31-4096 bytes as the maximum
        // resident set size.  Without the "if" condition below, the
        // second command below prints 0 as the maximum resident set
        // size.
        
        // ./timemem-darwin ../../memuse/test-memuse 2096863
        // ./timemem-darwin ../../memuse/test-memuse 2096864
        
        // Reference:
        // http://lists.apple.com/archives/darwin-kernel/2009/Mar/msg00005.html

        if (r.ru_maxrss == 0L) {
            // Print 2^31 bytes exactly
            fprintf(stderr, "2147483648  maximum resident set size from getrusage\n");
        } else {
            fprintf(stderr, "%10lu  maximum resident set size from getrusage\n",
                    (unsigned long) r.ru_maxrss);
        }
    }
    if (ps.use_polling) {
        long delta = (long) ps.max_rss_bytes - (long) r.ru_maxrss;
        fprintf(stderr, "%10lu  maximum resident set size from polling (%.1f MB, delta %ld bytes = %.1f MB)\n",
                (unsigned long) ps.max_rss_bytes,
                (double) ps.max_rss_bytes / (1024.0 * 1024.0),
                delta,
                (double) delta / (1024.0 * 1024.0));
        double elapsed_time_sec = (double) elapsed_msec / 1000.0;
        fprintf(stderr,
                "number of times rss polled=%ld, avg of %.1f times per second\n", 
                ps.num_polls,
                (double) ps.num_polls / elapsed_time_sec);
        fprintf(stderr,
                "time between consecutive polls (msec): min=%.1f max=%.1f\n",
                (double) ps.consecutive_poll_separation_min_msec,
                (double) ps.consecutive_poll_separation_max_msec);
        int64 max_rss_first_seen_msec =
            timeval_diff_msec(&start_time,
                              &(ps.poll_time_when_maxrss_first_seen));
        fprintf(stderr, "Max RSS observed %.1f sec after start time\n",
                (double) max_rss_first_seen_msec / 1000.0);
        if (ps.task_info_errored) {
            int64 diff_msec = timeval_diff_msec(&end_time,
                                                &(ps.task_info_error_time));
            if (diff_msec <= 0 && diff_msec >= -100) {
                // Then the error most likely occurred because the
                // child process had already exited.  Ignore it.
            } else {
                fprintf(stderr, "A call to task_info() returned an error.  error_time - end_time = %.3f sec.  This may mean the maximum resident set size measurement above is too low.\n",
                        (double) diff_msec / 1000.0);
            }
        }
    }

    // Show separate busy percentage for each CPU core
    fprintf(stderr, "Per core CPU utilization (%d cores):", num_cpus);
    for (i = 0; i < num_cpus; i++) {
        uint64 total = (per_cpu_stats_end[i].total -
                        per_cpu_stats_start[i].total);
        int cpu_busy_percent = 0;
        if (total != 0) {
            uint64 idle = (per_cpu_stats_end[i].idle -
                           per_cpu_stats_start[i].idle);
            cpu_busy_percent =
                (int) round(100.0 * (1.0 - ((float) idle)/total));
        }
        fprintf(stderr, " %d%%", cpu_busy_percent);
    }
    fprintf(stderr, "\n");
    
    if (WIFEXITED(wait_status)) {
        // Exit with the same status that the child process did.
        exit(WEXITSTATUS(wait_status));
    } else if (WIFSIGNALED(wait_status)) {
        fprintf(stderr,
                "Command stopped due to signal %d without calling exit().\n",
                WTERMSIG(wait_status));
        exit(1);
    } else {
        fprintf(stderr,
                "Command is stopped due to signal %d, and can be restarted.\n",
                WSTOPSIG(wait_status));
        exit(2);
    }

    return 0;
}
예제 #10
0
파일: ifstats.c 프로젝트: ebichu/dd-wrt
void ifstats(const struct OPTIONS *options, struct filterstate *ofilter,
	     time_t facilitytime)
{
	int logging = options->logging;
	struct iftab table;

	int pkt_result = 0;

	struct iflist *ptmp = NULL;

	unsigned int idx = 1;

	FILE *logfile = NULL;

	int ch;

	int fd;

	struct timeval tv;
	time_t starttime = 0;
	time_t statbegin = 0;
	time_t now = 0;
	struct timeval start_tv;
	unsigned long long unow = 0;
	time_t startlog = 0;
	time_t updtime = 0;
	unsigned long long updtime_usec = 0;

	struct promisc_states *promisc_list;

	if (!facility_active(GSTATIDFILE, ""))
		mark_facility(GSTATIDFILE, "general interface statistics", "");
	else {
		write_error("General interface stats already active in another process");
		return;
	}

	initiflist(&(table.head));
	if (table.head == NULL) {
		no_ifaces_error();
		unmark_facility(GSTATIDFILE, "");
		return;
	}

	initiftab(&table);

	if ((first_active_facility()) && (options->promisc)) {
		init_promisc_list(&promisc_list);
		save_promisc_list(promisc_list);
		srpromisc(1, promisc_list);
		destroy_promisc_list(&promisc_list);
	}

	adjust_instance_count(PROCCOUNTFILE, 1);

	if (logging) {
		if (strcmp(current_logfile, "") == 0) {
			strcpy(current_logfile, GSTATLOG);

			if (!daemonized)
				input_logfile(current_logfile, &logging);
		}
	}

	if (logging) {
		opentlog(&logfile, GSTATLOG);

		if (logfile == NULL)
			logging = 0;
	}
	if (logging) {
		signal(SIGUSR1, rotate_gstat_log);

		rotate_flag = 0;
		writelog(logging, logfile,
			 "******** General interface statistics started ********");
	}

	preparescreen(&table);

	update_panels();
	doupdate();

	fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
	if(fd == -1) {
		write_error("Unable to obtain monitoring socket");
		goto err;
	}

	//isdnfd = -1;
	exitloop = 0;
	gettimeofday(&tv, NULL);
	start_tv = tv;
	starttime = startlog = statbegin = tv.tv_sec;

	PACKET_INIT(pkt);

	while (!exitloop) {
		gettimeofday(&tv, NULL);
		now = tv.tv_sec;
		unow = tv.tv_sec * 1000000ULL + tv.tv_usec;

		if ((now - starttime) >= 1) {
			unsigned long msecs;

			msecs = timeval_diff_msec(&tv, &start_tv);
			updaterates(&table, options->actmode, msecs, idx);
			printelapsedtime(statbegin, now, LINES - 3, 1,
					 table.borderwin);
			starttime = now;
			start_tv = tv;
		}
		if (logging) {
			check_rotate_flag(&logfile);
			if ((now - startlog) >= options->logspan) {
				writegstatlog(&table, options->actmode,
					      time(NULL) - statbegin,
					      logfile);
				startlog = now;
			}
		}
		if (((options->updrate != 0)
		     && (now - updtime >= options->updrate))
		    || ((options->updrate == 0)
			&& (unow - updtime_usec >= DEFAULT_UPDATE_DELAY))) {
			update_panels();
			doupdate();
			updtime = now;
			updtime_usec = unow;
		}

		if ((facilitytime != 0)
		    && (((now - statbegin) / 60) >= facilitytime))
			exitloop = 1;

		if (packet_get(fd, &pkt, &ch, table.statwin) == -1) {
			write_error("Packet receive failed");
			exitloop = 1;
			break;
		}

		switch (ch) {
		case ERR:
			/* no key ready, do nothing */
			break;
		case KEY_UP:
			scrollgstatwin(&table, SCROLLDOWN, &idx);
			break;
		case KEY_DOWN:
			scrollgstatwin(&table, SCROLLUP, &idx);
			break;
		case KEY_PPAGE:
		case '-':
			pagegstatwin(&table, SCROLLDOWN, &idx);
			break;
		case KEY_NPAGE:
		case ' ':
			pagegstatwin(&table, SCROLLUP, &idx);
			break;
		case 12:
		case 'l':
		case 'L':
			tx_refresh_screen();
			break;
		case 'Q':
		case 'q':
		case 'X':
		case 'x':
		case 27:
		case 24:
			exitloop = 1;
			break;
		}
		if (pkt.pkt_len <= 0)
			continue;

		pkt_result = packet_process(&pkt, NULL, NULL, NULL,
					   ofilter,
					   MATCH_OPPOSITE_USECONFIG,
					   options->v6inv4asv6);

		if (pkt_result != PACKET_OK
		    && pkt_result != MORE_FRAGMENTS)
			continue;

		ptmp = positionptr(table.head, pkt.pkt_ifindex);
		if (!ptmp)
			continue;

		ptmp->total++;

		ptmp->spanbr += pkt.pkt_len;
		ptmp->br += pkt.pkt_len;

		if (pkt.pkt_protocol == ETH_P_IP) {
			ptmp->iptotal++;

			if (pkt_result == CHECKSUM_ERROR) {
				(ptmp->badtotal)++;
				continue;
			}
		} else if (pkt.pkt_protocol == ETH_P_IPV6) {
			ptmp->ip6total++;
		} else {
			(ptmp->noniptotal)++;
		}
		printifentry(ptmp, table.statwin, idx);
	}
	close(fd);

err:
	if ((options->promisc) && (is_last_instance())) {
		load_promisc_list(&promisc_list);
		srpromisc(0, promisc_list);
		destroy_promisc_list(&promisc_list);
	}

	adjust_instance_count(PROCCOUNTFILE, -1);

	del_panel(table.statpanel);
	delwin(table.statwin);
	del_panel(table.borderpanel);
	delwin(table.borderwin);
	update_panels();
	doupdate();

	if (logging) {
		signal(SIGUSR1, SIG_DFL);
		writegstatlog(&table, options->actmode,
			      time(NULL) - statbegin, logfile);
		writelog(logging, logfile,
			 "******** General interface statistics stopped ********");
		fclose(logfile);
	}
	destroyiflist(table.head);
	pkt_cleanup();
	unmark_facility(GSTATIDFILE, "");
	strcpy(current_logfile, "");
}