/** Implements the end_interval function of the plugin API */ int bgpcorsaro_pacifier_end_interval(bgpcorsaro_t *bgpcorsaro, bgpcorsaro_interval_t *int_end) { struct bgpcorsaro_pacifier_state_t *state = STATE(bgpcorsaro); bgpcorsaro_io_write_interval_end(bgpcorsaro, state->outfile, int_end); /* if we are rotating, now is when we should do it */ if(bgpcorsaro_is_rotate_interval(bgpcorsaro)) { /* leave the current file to finish draining buffers */ assert(state->outfile != NULL); /* move on to the next output pointer */ state->outfile_n = (state->outfile_n+1) % OUTFILE_POINTERS; if(state->outfile_p[state->outfile_n] != NULL) { /* we're gonna have to wait for this to close */ wandio_wdestroy(state->outfile_p[state->outfile_n]); state->outfile_p[state->outfile_n] = NULL; } state->outfile = NULL; } struct timeval tv; gettimeofday_wrap(&tv); int expected_time = 0; int diff = 0; if(state->adaptive == 0) { diff = state->wait - (tv.tv_sec - state->tv_start); } else { expected_time = state->tv_first_time + state->intervals * state->wait; diff = expected_time - tv.tv_sec ; } // if the end interval is faster than "the wait" time // then we wait for the remaining seconds if(diff > 0) { // fprintf(stderr, "\tWaiting: %d s\n", diff); sleep(diff); gettimeofday_wrap(&tv); } state->tv_start = tv.tv_sec; // fprintf(stderr, "END INTERVAL TIME: %d \n", state->tv_start); return 0; }
/* * scamper_fds_poll * * the money function: this function polls the file descriptors held by * scamper. for each fd with an event, it calls the callback registered * with the fd. */ int scamper_fds_poll(struct timeval *timeout) { scamper_fd_t *fdn; struct timeval tv; /* * if there are fds that can be reaped, then do so. * if there are fds left over after, use that to guide the select timeout. */ if(dlist_count(refcnt_0) > 0) { gettimeofday_wrap(&tv); while((fdn = (scamper_fd_t *)dlist_head_get(refcnt_0)) != NULL) { assert(fdn->refcnt == 0); if(timeval_cmp(&fdn->tv, &tv) > 0) break; fd_close(fdn); fd_free(fdn); } if(fdn != NULL) { timeval_diff_tv(&tv, &tv, &fdn->tv); if(timeout == NULL || timeval_cmp(&tv, timeout) < 0) timeout = &tv; } } return pollfunc(timeout); }
static int do_method(void) { struct timeval tv; char *command; if(slist_count(commands) == 0) return 0; gettimeofday_wrap(&tv); command = slist_head_pop(commands); write_wrap(scamper_fd, command, NULL, strlen(command)); more--; if((options & OPT_DEBUG) != 0) fprintf(stderr, "%ld: %s", (long int)tv.tv_sec, command); if(lastcommand != NULL) free(lastcommand); lastcommand = command; if(slist_count(commands) == 0 && stdin_fd == -1 && done == 0) { write_wrap(scamper_fd, "done\n", NULL, 5); done = 1; } return 0; }
static char *timestamp_str(char *buf, const size_t len) { struct timeval tv; struct tm *tm; int ms; time_t t; buf[0] = '\0'; gettimeofday_wrap(&tv); t = tv.tv_sec; if((tm = localtime(&t)) == NULL) return buf; ms = tv.tv_usec / 1000; snprintf(buf, len, "[%02d:%02d:%02d:%03d] ", tm->tm_hour, tm->tm_min, tm->tm_sec, ms); return buf; }
static void probe_dlhdr_cb(scamper_dlhdr_t *dlhdr) { probe_t *pr = dlhdr->param; scamper_fd_t *fd = NULL; scamper_dl_t *dl = NULL; uint8_t *pkt; if(dlhdr->error != 0) { pr->error = dlhdr->error; goto err; } assert(dlhdr->len < 16); pkt = pr->buf+16-dlhdr->len; if(dlhdr->len > 0) memcpy(pkt, dlhdr->buf, dlhdr->len); if((fd = scamper_task_fd_dl(pr->task, pr->rt->ifindex)) == NULL) { pr->error = EINVAL; goto err; } if(pr->buf == pktbuf) gettimeofday_wrap(&pr->tv); dl = scamper_fd_dl_get(fd); if(scamper_dl_tx(dl, pkt, dlhdr->len + pr->len) == -1) { pr->error = errno; goto err; } pr->mode = PROBE_MODE_TX; goto done; err: pr->mode = PROBE_MODE_ERR; done: if(pr->anc != NULL) probe_free(pr); return; }
/* * fd_refcnt_0 * * this function is called whenever a fdn with a refcnt field of zero is * found. */ static void fd_refcnt_0(scamper_fd_t *fdn) { /* * if the fd is in a list that is currently locked, then it can't be * removed just yet */ if(dlist_islocked(fd_list) != 0 || (fdn->read.list != NULL && dlist_islocked(fdn->read.list) != 0) || (fdn->write.list != NULL && dlist_islocked(fdn->write.list) != 0)) { return; } /* * if this is a private fd and the reference count has reached zero, * then the scamper_fd structure can be freed up completely now */ if(fdn->type == SCAMPER_FD_TYPE_PRIVATE) { fd_free(fdn); return; } /* if it is not possible to put the node on a list, just free it */ if((fdn->rc0 = dlist_tail_push(refcnt_0, fdn)) == NULL) { fd_close(fdn); fd_free(fdn); return; } /* * set this fd to be closed in ten seconds unless something else comes * along and wants to use it. */ gettimeofday_wrap(&fdn->tv); fdn->tv.tv_sec += 10; return; }
/** Implements the start_interval function of the plugin API */ int bgpcorsaro_pacifier_start_interval(bgpcorsaro_t *bgpcorsaro, bgpcorsaro_interval_t *int_start) { struct bgpcorsaro_pacifier_state_t *state = STATE(bgpcorsaro); if(state->outfile == NULL) { if(( state->outfile_p[state->outfile_n] = bgpcorsaro_io_prepare_file(bgpcorsaro, PLUGIN(bgpcorsaro)->name, int_start)) == NULL) { bgpcorsaro_log(__func__, bgpcorsaro, "could not open %s output file", PLUGIN(bgpcorsaro)->name); return -1; } state->outfile = state-> outfile_p[state->outfile_n]; } bgpcorsaro_io_write_interval_start(bgpcorsaro, state->outfile, int_start); struct timeval tv; if(state->tv_start == 0) { gettimeofday_wrap(&tv); state->tv_start = tv.tv_sec; state->tv_first_time = state->tv_start; } // a new interval is starting state->intervals++; // fprintf(stderr, "START INTERVAL TIME: %d \n", state->tv_start); return 0; }
static int addr2mac_init_linux() { struct nlmsghdr *nlmsg; struct ndmsg *ndmsg; struct rtattr *rta, *tb[NDA_MAX]; struct sockaddr_nl snl; struct msghdr msg; struct iovec iov; struct timeval tv; pid_t pid; uint8_t buf[16384]; ssize_t ssize; ssize_t len; int rlen; int fd = -1; void *ip, *mac; int iptype; pid = getpid(); memset(buf, 0, sizeof(buf)); nlmsg = (struct nlmsghdr *)buf; nlmsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)); nlmsg->nlmsg_type = RTM_GETNEIGH; nlmsg->nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT | NLM_F_MATCH; nlmsg->nlmsg_seq = 0; nlmsg->nlmsg_pid = pid; ndmsg = NLMSG_DATA(nlmsg); ndmsg->ndm_family = AF_UNSPEC; if((fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) == -1) { printerror(errno, strerror, __func__, "could not open netlink"); goto err; } len = nlmsg->nlmsg_len; if((ssize = send(fd, buf, len, 0)) < len) { if(ssize == -1) { printerror(errno, strerror, __func__, "could not send netlink"); } goto err; } for(;;) { iov.iov_base = buf; iov.iov_len = sizeof(buf); msg.msg_name = &snl; msg.msg_namelen = sizeof(snl); msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_control = NULL; msg.msg_controllen = 0; msg.msg_flags = 0; if((len = recvmsg(fd, &msg, 0)) == -1) { if(errno == EINTR) continue; printerror(errno, strerror, __func__, "could not recvmsg"); goto err; } gettimeofday_wrap(&tv); nlmsg = (struct nlmsghdr *)buf; while(NLMSG_OK(nlmsg, len)) { if(nlmsg->nlmsg_pid != pid || nlmsg->nlmsg_seq != 0) { goto skip; } if(nlmsg->nlmsg_type == NLMSG_DONE) { goto done; } if(nlmsg->nlmsg_type == NLMSG_ERROR) { scamper_debug(__func__, "nlmsg error"); goto err; } /* get current neighbour entries only */ if(nlmsg->nlmsg_type != RTM_NEWNEIGH) { goto skip; } /* make sure the address is reachable */ ndmsg = NLMSG_DATA(nlmsg); if((ndmsg->ndm_state & NUD_REACHABLE) == 0) { goto skip; } /* make sure we can process this address type */ switch(ndmsg->ndm_family) { case AF_INET: iptype = SCAMPER_ADDR_TYPE_IPV4; break; case AF_INET6: iptype = SCAMPER_ADDR_TYPE_IPV6; break; default: goto skip; } /* fill a table with parameters from the payload */ memset(tb, 0, sizeof(tb)); rlen = nlmsg->nlmsg_len - NLMSG_LENGTH(sizeof(struct ndmsg)); for(rta = NDA_RTA(ndmsg); RTA_OK(rta,rlen); rta = RTA_NEXT(rta,rlen)) { if(rta->rta_type >= NDA_MAX) continue; tb[rta->rta_type] = rta; } /* * skip if we don't have a destination IP address, or if * we don't have an ethernet mac address */ if(tb[NDA_DST] == NULL || tb[NDA_LLADDR] == NULL || RTA_PAYLOAD(tb[NDA_LLADDR]) != 6) { goto skip; } ip = RTA_DATA(tb[NDA_DST]); mac = RTA_DATA(tb[NDA_LLADDR]); addr2mac_add(ndmsg->ndm_ifindex, iptype, ip, mac, tv.tv_sec+600); skip: nlmsg = NLMSG_NEXT(nlmsg, len); } } done: close(fd); return 0; err: close(fd); return -1; }
/* * scamper_probe_send * * this meta-function is responsible for * 1. sending a probe * 2. handling any error condition incurred when sending the probe * 3. recording details of the probe with the trace's state */ int scamper_probe(scamper_probe_t *probe) { int (*send_func)(scamper_probe_t *) = NULL; int (*build_func)(scamper_probe_t *, uint8_t *, size_t *) = NULL; size_t pad, len; uint8_t *buf; probe->pr_errno = 0; probe_print(probe); /* determine which function scamper should use to build or send the probe */ if(probe->pr_ip_dst->type == SCAMPER_ADDR_TYPE_IPV4) { if((probe->pr_ip_off & IP_OFFMASK) != 0) { build_func = scamper_ip4_frag_build; } else if(probe->pr_ip_proto == IPPROTO_UDP) { send_func = scamper_udp4_probe; build_func = scamper_udp4_build; } else if(probe->pr_ip_proto == IPPROTO_TCP) { build_func = scamper_tcp4_build; if(probe->pr_fd != -1) send_func = scamper_tcp4_probe; } else if(probe->pr_ip_proto == IPPROTO_ICMP) { send_func = scamper_icmp4_probe; build_func = scamper_icmp4_build; } } else if(probe->pr_ip_dst->type == SCAMPER_ADDR_TYPE_IPV6) { if(probe->pr_ip_off != 0) { build_func = scamper_ip6_frag_build; } else if(probe->pr_ip_proto == IPPROTO_UDP) { send_func = scamper_udp6_probe; build_func = scamper_udp6_build; } else if(probe->pr_ip_proto == IPPROTO_TCP) { build_func = scamper_tcp6_build; } else if(probe->pr_ip_proto == IPPROTO_ICMPV6) { send_func = scamper_icmp6_probe; build_func = scamper_icmp6_build; } } /* if we're not using the datalink to send the packet, then send it now */ if(probe->pr_dl == NULL) { if(send_func != NULL) return send_func(probe); probe->pr_errno = EINVAL; return -1; } /* if the header type is not known (we cannot build it) then bail */ if(build_func == NULL) { probe->pr_errno = EINVAL; return -1; } /* * determine a suitable value for the length parameter for passing * to build_func. to do so we also need to calculate the number of pad * bytes to put at the front of the packet buffer so that the IP layer * is properly aligned for the architecture */ pad = PAD(probe->pr_dl_len); if(pad + probe->pr_dl_len >= pktbuf_len) len = 0; else len = pktbuf_len - pad - probe->pr_dl_len; /* * try building the probe. if it returns -1, then hopefully the len field * will supply a clue as to what it should be */ if(build_func(probe, pktbuf + pad + probe->pr_dl_len, &len) != 0) { assert(pktbuf_len < pad + probe->pr_dl_len + len); /* reallocate the packet buffer */ len += pad + probe->pr_dl_len; if((buf = realloc(pktbuf, len)) == NULL) { probe->pr_errno = errno; printerror(errno, strerror, __func__, "could not realloc"); return -1; } pktbuf = buf; pktbuf_len = len; len = pktbuf_len - pad - probe->pr_dl_len; if(build_func(probe, pktbuf + pad + probe->pr_dl_len, &len) != 0) { probe->pr_errno = EINVAL; return -1; } } /* add the datalink header size back to the length field */ len += probe->pr_dl_len; /* pre-pend the datalink header, if there is one */ if(probe->pr_dl_len > 0) memcpy(pktbuf+pad, probe->pr_dl_buf, probe->pr_dl_len); gettimeofday_wrap(&probe->pr_tx); if(scamper_dl_tx(probe->pr_dl, pktbuf+pad, len) == -1) { probe->pr_errno = errno; return -1; } probe->pr_tx_raw = pktbuf + pad + probe->pr_dl_len; probe->pr_tx_rawlen = len - probe->pr_dl_len; return 0; }
int scamper_probe_task(scamper_probe_t *pr, scamper_task_t *task) { probe_t *pt = NULL; scamper_fd_t *icmp = NULL; scamper_fd_t *fd; int spoof = 0; uint16_t sp; void *src = NULL; int dl = 0; probe_print(pr); if((pr->pr_flags & SCAMPER_PROBE_FLAG_SPOOF) != 0) spoof = 1; /* get an ICMP socket to listen for responses */ if(SCAMPER_ADDR_TYPE_IS_IPV4(pr->pr_ip_dst)) { if(spoof == 0) { src = pr->pr_ip_src->addr; if((icmp = scamper_task_fd_icmp4(task, src)) == NULL) { pr->pr_errno = errno; goto err; } } } else if(SCAMPER_ADDR_TYPE_IS_IPV6(pr->pr_ip_dst)) { if(spoof == 0) { src = pr->pr_ip_src->addr; if((icmp = scamper_task_fd_icmp6(task, src)) == NULL) { pr->pr_errno = errno; goto err; } } } else { scamper_debug(__func__, "missing destination address"); pr->pr_errno = EINVAL; goto err; } /* * even though many operating systems allow the use of RAW TCP sockets to * send TCP probes, we still need to be able to receive TCP responses. * so we use a datalink socket to both send and receive TCP probes rather * than open both a socket to send and another to receive. */ if(dl == 0 && pr->pr_ip_proto == IPPROTO_TCP) dl = 1; else if(dl == 0 && ipid_dl != 0 && SCAMPER_PROBE_IS_IPID(pr)) dl = 1; else if(dl == 0 && (pr->pr_flags & SCAMPER_PROBE_FLAG_NOFRAG)) dl = 1; else if(dl == 0 && spoof != 0) dl = 1; if(dl != 0) { if((pt = probe_build(pr)) == NULL) { pr->pr_errno = errno; goto err; } pt->task = task; pt->mode = PROBE_MODE_RT; pt->rt = scamper_route_alloc(pr->pr_ip_dst, pt, probe_route_cb); if(pt->rt == NULL) { pr->pr_errno = errno; goto err; } #ifndef _WIN32 if((pt->rtsock = scamper_task_fd_rtsock(task)) == NULL) { pr->pr_errno = errno; goto err; } if(scamper_rtsock_getroute(pt->rtsock, pt->rt) != 0) { pr->pr_errno = errno; goto err; } #else if(scamper_rtsock_getroute(pt->rt) != 0) { pr->pr_errno = errno; goto err; } #endif if(pt->mode == PROBE_MODE_ERR) { pr->pr_errno = pt->error; goto err; } if(pt->mode != PROBE_MODE_TX) { if((pt->buf = memdup(pktbuf, pt->len + 16)) == NULL) { pr->pr_errno = errno; goto err; } if((pt->anc = scamper_task_anc_add(task, pt, probe_free_cb)) == NULL) { pr->pr_errno = errno; goto err; } gettimeofday_wrap(&pr->pr_tx); } else { timeval_cpy(&pr->pr_tx, &pt->tv); probe_free(pt); } return 0; } else if(SCAMPER_ADDR_TYPE_IS_IPV4(pr->pr_ip_dst)) { if(pr->pr_ip_proto == IPPROTO_UDP) { sp = pr->pr_udp_sport; if((fd = scamper_task_fd_udp4(task, src, sp)) == NULL) { pr->pr_errno = errno; goto err; } pr->pr_fd = scamper_fd_fd_get(fd); if(scamper_udp4_probe(pr) != 0) { pr->pr_errno = errno; goto err; } } else if(pr->pr_ip_proto == IPPROTO_ICMP) { pr->pr_fd = scamper_fd_fd_get(icmp); if(scamper_icmp4_probe(pr) != 0) { pr->pr_errno = errno; goto err; } } else { scamper_debug(__func__, "unhandled protocol %d", pr->pr_ip_proto); pr->pr_errno = EINVAL; /* actually a bug in the caller */ goto err; } } else if(SCAMPER_ADDR_TYPE_IS_IPV6(pr->pr_ip_dst)) { if(pr->pr_ip_proto == IPPROTO_UDP) { sp = pr->pr_udp_sport; if((fd = scamper_task_fd_udp6(task, src, sp)) == NULL) { pr->pr_errno = errno; goto err; } pr->pr_fd = scamper_fd_fd_get(fd); if(scamper_udp6_probe(pr) != 0) { pr->pr_errno = errno; goto err; } } else if(pr->pr_ip_proto == IPPROTO_ICMPV6) { pr->pr_fd = scamper_fd_fd_get(icmp); if(scamper_icmp6_probe(pr) != 0) { pr->pr_errno = errno; goto err; } } else { pr->pr_errno = EINVAL; /* actually a bug in the caller */ goto err; } } else { pr->pr_errno = EINVAL; goto err; } return 0; err: printerror(pr->pr_errno, strerror, __func__, "could not probe"); if(pt != NULL) probe_free(pt); return -1; }