1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284
|
/* $Id: probe.c,v 0.2 2000/12/20 14:29:45 kjc Exp kjc $ */
/*
* Copyright (c) 1996-2000
* Sony Computer Science Laboratories, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms of parts of or the
* whole original or derived work are permitted provided that the above
* copyright notice is retained and the original work is properly
* attributed to the author. The name of the author may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
/* probe.c -- a probe program main module for remote-monitoring. */
#include <stdio.h>
#include <signal.h>
#include <netdb.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include "ttt.h"
#include "ttt_node.h"
#include "ttt_remote.h"
#include <pcap.h>
extern pcap_t *pd;
extern void (*ttt_netreader)(u_char *user, const struct pcap_pkthdr *h, const u_char *p);
static int sockfd;
static struct sockaddr_in view_addr;
static u_long f_localnet, f_netmask;
static void probe_loop(int pcapfd, int sock_fd);
static int send_report(int sock_fd, int seq_no, struct timeval *tvp);
static int write_record(struct t_node *np, struct ttt_record *trp);
static void probe_cleanup(void);
/* a net_subr compatible procudure just to save localnet address */
void netname_init(u_long netaddr, u_long netmask)
{
/* save localnet address and netmask */
f_localnet = netaddr;
f_netmask = netmask;
}
static void usage(void)
{
printf("usage: probe [options] dest\n");
printf(" or probe [options] -multicast\n");
printf(" options:\n");
printf(" [-interface device]\n");
printf(" [-port dest_port]\n");
printf(" [-ttl time-to-live]\n");
printf(" [-interval msec]\n");
exit(1);
}
int main(int argc, char **argv)
{
struct sockaddr_in my_addr;
int pcapfd;
u_char ttl = 1; /* time-to-live field for mcast */
int port_no = TTT_PORT; /* receiver's port number */
int multicast = 0; /* use multicast */
char *view_name = NULL;
char *my_name = NULL;
while (--argc > 0) {
if (strcmp(*++argv, "-interface") == 0 && --argc > 0)
ttt_interface = *++argv;
else if (strncmp(*argv, "-multicast", 4) == 0)
view_name = TTT_MCASTADDR;
else if (strncmp(*argv, "-port", 4) == 0 && --argc > 0)
port_no = atoi(*++argv);
else if (strcmp(*argv, "-interval") == 0 && --argc > 0)
ttt_interval = atoi(*++argv);
else if (strcmp(*argv, "-ttl") == 0 && --argc > 0)
ttl = atoi(*++argv);
else if (view_name == NULL)
view_name = *argv;
else
usage();
}
if (view_name == NULL) {
printf("no destination specified!\n");
usage();
}
if (name2sockaddrin(my_name, 0, &my_addr) < 0)
fatal_error("can't get my address!");
if (name2sockaddrin(view_name, port_no, &view_addr) < 0)
fatal_error("can't get viewer's address!");
#ifdef IN_MULTICAST
if (IN_MULTICAST(ntohl(view_addr.sin_addr.s_addr)))
multicast = 1;
#endif
if ((sockfd = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
fatal_error("sender: can't open socket");
#ifdef IP_MULTICAST_TTL
if (multicast && ttl != 1)
if (setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL,
&ttl, sizeof(ttl)) < 0)
fatal_error("can't set ttl");
#endif
if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(my_addr)) < 0)
fatal_error("sender: can't bind");
netacc_init();
pcapfd = open_pf(ttt_interface);
printf("probe started. sending to %s:%d ....\n",
inet_ntoa(view_addr.sin_addr), port_no);
probe_loop(pcapfd, sockfd);
/* never returns */
probe_cleanup();
return 0;
}
static void probe_cleanup(void)
{
close(sockfd);
close_pf();
netacc_cleanup();
}
#define BUFFER_SIZE 4096 /* big enough */
static char buffer[BUFFER_SIZE];
/* timeval macros from Xt */
#define ADD_TIME(dest, src1, src2) { \
if(((dest).tv_usec = (src1).tv_usec + (src2).tv_usec) >= 1000000) {\
(dest).tv_usec -= 1000000;\
(dest).tv_sec = (src1).tv_sec + (src2).tv_sec + 1 ; \
} else { (dest).tv_sec = (src1).tv_sec + (src2).tv_sec ; \
if(((dest).tv_sec >= 1) && (((dest).tv_usec <0))) { \
(dest).tv_sec --;(dest).tv_usec += 1000000; } } }
#define TIMEDELTA(dest, src1, src2) { \
if(((dest).tv_usec = (src1).tv_usec - (src2).tv_usec) < 0) {\
(dest).tv_usec += 1000000;\
(dest).tv_sec = (src1).tv_sec - (src2).tv_sec - 1;\
} else (dest).tv_sec = (src1).tv_sec - (src2).tv_sec; }
#define IS_AFTER(t1, t2) (((t2).tv_sec > (t1).tv_sec) \
|| (((t2).tv_sec == (t1).tv_sec)&& ((t2).tv_usec > (t1).tv_usec)))
#define IS_AT_OR_AFTER(t1, t2) (((t2).tv_sec > (t1).tv_sec) \
|| (((t2).tv_sec == (t1).tv_sec)&& ((t2).tv_usec >= (t1).tv_usec)))
static void probe_loop(int pcapfd, int sock_fd)
{
struct timeval cur_time, wait_time, expr_time, interval;
fd_set rmaskfd;
int seq_no, nfound;
interval.tv_sec = ttt_interval/1000;
interval.tv_usec = (ttt_interval%1000)*1000;
(void) gettimeofday(&cur_time, NULL);
ADD_TIME(expr_time, cur_time, interval);
seq_no = 1;
while (1) {
(void) gettimeofday(&cur_time, NULL);
/* check time to send a ttt report */
if (IS_AT_OR_AFTER(expr_time, cur_time)) {
if (send_report(sockfd, seq_no, &cur_time) > 0)
seq_no++;
ADD_TIME(expr_time, cur_time, interval);
}
wait_time.tv_sec = wait_time.tv_usec = 0;
TIMEDELTA(wait_time, expr_time, cur_time);
FD_ZERO(&rmaskfd);
FD_SET(pcapfd, &rmaskfd);
nfound = select(pcapfd+1, &rmaskfd, NULL, NULL, &wait_time);
if (nfound == -1) {
/* interrupt occured recalculate time value and select again. */
perror("select");
continue;
}
if (FD_ISSET(pcapfd, &rmaskfd)) {
if (pcap_dispatch(pd, 1, ttt_netreader, 0) < 0)
(void)fprintf(stderr, "pcap_dispatch:%s\n", pcap_geterr(pd));
}
}
}
/* create a report packet and send it out */
static int send_report(int sock_fd, int seq_no, struct timeval *tvp)
{
struct ttt_hdr *hdr;
int protos, hosts, rsize, rval;
char *cp;
struct t_node *np;
struct pcap_stat pc_stat;
static int last_sent = 1; /* how many records sent last time.
initial value 1 is to send first packet */
hdr = (struct ttt_hdr *)buffer;
hdr->th_magic = htons(TTT_MAGIC);
hdr->th_version = htons((TTT_MAJOR<<8) | TTT_MINOR);
hdr->th_network = f_localnet;
hdr->th_seqno = htonl(seq_no);
hdr->th_tvsec = htonl(tvp->tv_sec);
hdr->th_tvusec = htonl(tvp->tv_usec);
/* get pcap statistics */
if (pcap_stats(pd, &pc_stat) == 0) {
hdr->th_recvpkts = htonl(pc_stat.ps_recv);
hdr->th_droppkts = htonl(pc_stat.ps_drop);
}
else {
hdr->th_recvpkts = 0;
hdr->th_droppkts = 0;
}
/* get the top 10 traffic of this interval. */
cp = buffer + sizeof(struct ttt_hdr);
for (protos=0, np = node_getbiggest(TTTTYPE_PROTO);
protos<10 && np != NULL; protos++, np = node_getnext(np)) {
rsize = write_record(np, (struct ttt_record *)cp);
cp += rsize;
}
for (hosts=0, np = node_getbiggest(TTTTYPE_HOST);
hosts<10 && np != NULL; hosts++, np = node_getnext(np)) {
rsize = write_record(np, (struct ttt_record *)cp);
cp += rsize;
}
hdr->th_nrecords = htonl(protos + hosts);
node_bumptime(); /* give a time tick to the node module */
#if 0 /* if the traffic is this low, why bothering to send a packet? */
if ((protos+hosts) == 0 && last_sent == 0) {
/* no traffic, nothing to send */
return 0;
}
last_sent = protos + hosts;
#endif
if ((rval = sendto(sock_fd, buffer, cp - buffer, 0,
(struct sockaddr *)&view_addr, sizeof(view_addr))) < 0)
perror("sendto");
return rval;
}
/* write node info to ttt_record */
static int write_record(struct t_node *np, struct ttt_record *trp)
{
struct ttt_record6 *tr6p;
if (np->t_type != TTTTYPE_IPV6HOST) {
trp->tr_type = htonl(np->t_type);
trp->tr_size = htonl(np->t_size);
trp->tr_id[0] = htonl(np->t_id[0]);
return sizeof(struct ttt_record);
}
else {
tr6p = (struct ttt_record6 *)trp;
tr6p->tr_type = htonl(np->t_type);
tr6p->tr_size = htonl(np->t_size);
tr6p->tr_id[0] = htonl(np->t_id[0]);
tr6p->tr_id[1] = htonl(np->t_id[1]);
tr6p->tr_id[2] = htonl(np->t_id[2]);
tr6p->tr_id[3] = htonl(np->t_id[3]);
return sizeof(struct ttt_record6);
}
}
|