/** * \fn struct probe_response probe_icmp(int sockfd, struct sockaddr_in *destination) * \brief traite le lancement et la reception d'une sonde sur le réseau * \param sockfd, socket a utilisé pour le ping * \param destination, pointeur vers la structure sockaddr_in contenant les informations de la destination des paquets * \return une structure probe_response contenant les informations necessaire du paquet recu */ struct probe_response probe_icmp(int sockfd, struct sockaddr_in *destination) { struct packet pkt_r; struct icmp_header *pkt_s; struct probe_response response; struct timeval interval; response.source_ip = malloc(sizeof(uint32_t)); // response.status = PROBE_NO_RESPONSE; response.integrity_error = INTEGRITY_OK; response.time = TIMEOUT*1000; //Envoi le paquet ICMP if ((pkt_s = send_echo_request(sockfd, destination)) == NULL) { perror("Envoi de la sonde échoué "); response.status = PROBE_SEND_FAIL; } //Réinitialisation des valeurs necessaire a select interval.tv_sec = TIMEOUT; interval.tv_usec = 0; if (receive_packet(sockfd, &pkt_r, &interval) > 0) { response.status = PROBE_OK; // on a reçu une réponse } else return response; // Stock l'ip du routeur dans ip_string en format texte if(inet_ntop(AF_INET, &(pkt_r.ip.ip_src), response.source_ip, sizeof(char)*16) == NULL) { perror("echec inet_ntop"); response.integrity_error = 1; response.source_ip = NULL; } response.icmp = pkt_r.icmp; response.ttl = pkt_r.ip.ttl; if(!(pkt_r.icmp.type == 0 && pkt_r.icmp.id == pkt_s->id && pkt_r.icmp.seq_num == pkt_s->seq_num)) { response.integrity_error = INTEGRITY_ERROR; } response.time = (1000000 - (long int) interval.tv_usec) / 1000; if (TIMEOUT - 1 - interval.tv_sec > 0) response.time += (long int) (TIMEOUT - 1 - interval.tv_sec)*1000; return response; }
/* Send a set of pings to nodes in order */ void send_npings(nw_skt_t sock, I3ServerList *list, I3ServerListNode **node, int n) { int i; static int seq = 1; struct in_addr ia; n = MIN(n, list->num_ping_list); for (i = 0; i < n; i++) { ia.s_addr = htonl((*node)->addr); I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_VERBOSE, "Sending echo request to %s\n", inet_ntoa(ia)); #ifdef ICMP_PING send_echo_request(sock, (*node)->addr, seq); #else i3_echo_request(sock, (*node)->addr, (*node)->port, seq); #endif *node = (*node)->next_list; if (NULL == *node) { *node = list->list; seq++; } } }
/* * Function: main * Purpose: * Comments: */ int main(int argc, char *argv[]) { int i; struct sigaction si_sa; int euid, ruid; struct host_entry *cursor; /* * first things first * if anything goes wrong anywhere, we want to be super careful to release * any file descriptor we have on /dev/lkm, and it probably makes sense to * shutdown the raw socket we have too. */ atexit(cleanup); /* * get the effective and the real user id's so we know if we are running * with elevated permissions or not */ euid = geteuid(); ruid = getuid(); /* check for the command line arguments */ if(check_options(argc,argv) == 0) { return -1; } /* * open the raw socket now. i used to have this further down closer to * where it was needed, but because you can't change the euid/uid to and * from root (unless you're the superuser) i can only do this once */ if(options & OPT_IPV4) { if(open_ipmp_sockets4() == 0) return -1; } else if(options & OPT_IPV6) { if(open_ipmp_sockets6() == 0) return -1; } else { if(open_ipmp_sockets4() == 0) return -1; if(open_ipmp_sockets6() == 0) return -1; } /* * revoke the permissions we requested as we only need them to open a raw * socket. this is to reduce the impact of any buffer overflow exploits * that may be present */ if(ruid != euid) { setreuid(ruid, ruid); } /* * we get the pid so we can identify incoming ipmp packets destined for * this instance of ipmp_ping */ pid = getpid(); /* * need to know about the addresses this host has */ learn_localaddresses(); /* * in FreeBSD, the actual ping is done by a kernel module that has a syscall * in it. the kernel module allows the protocol to get a timestamp as close * to when the mbuf is actually sent to ip_output as possible */ #if defined(__FreeBSD__) if((options & OPT_RAW) == 0) { i = get_syscall("ipmp_ping", &syscall_num); if(i != 0) { printerror(i, strerror, "could not get the syscall for ipmp_ping"); return -1; } } #endif /* * the -n option means that the user has supplied a list of hosts to * ping, so we read those entries and put them in an list of hosts with * details regarding each host. the task of putting hosts into the list * is handled by read_hosts_file * * if the -n option isnt specified, we create a list containing just the * one host to ping. this way, all the program logic can be used in a * multitude of situations. */ if(options & OPT_NLANR) { /* * if something went wrong parsing the file, we quit. */ if(read_hosts_file() == 0) { return -1; } } else { /* * if the user didnt specify a host to ping, we bail, telling them * why first... */ if(argc - optind != 1) { usage(0); return -1; } /* * if we can't add a host entry for the host supplied on the command line * tell the user that it couldnt be parse and cleanup */ if(add_host_entry(argv[optind], NULL) == 0) { return -1; } } /* * we now put some handlers into action so if the user ctrl-c's us we have * the opportunity to tell them what we found out first * also, if the user specified a timeout, put an alarm in for that so we * can bail when they tell us to... */ sigemptyset(&si_sa.sa_mask); si_sa.sa_flags = 0; si_sa.sa_handler = alarm_bells; if(sigaction(SIGINT, &si_sa, 0) == -1) { printerror(errno, strerror, "could not set sigaction for SIGINT"); return -1; } if(options & OPT_TIMEOUT) { if(sigaction(SIGALRM, &si_sa, 0) == -1) { printerror(errno, strerror, "could not set sigaction for SIGALRM"); return -1; } } /* * we loop for as long as we have not been told to finish up. * the finish_up loop will exit when * - there has been an alarm set that goes off * - a SIGINT is received (from e.g. Ctrl-C) * - we have got_all_response()'s * * this is not an expensive loop in terms of cpu cycles, as the * recv_echo_response will sleep if there is nothing to recv until we have * told it to stop blocking - typically one second or whatever the between * timeout is. * * the loop does two things: * - sends echo requests * - receives echo responses * * the loop sends packets, pausing for however long the timeout is set for * between packets. this pause is implemented in the recv_echo_response * function in a call to select(2). if we cannot send a request to one of * them, we bail, as this probably means the syscall could not be called. * * the loop recv's the response and associates the packet with a host_entry * we then parse that response for the host entry, and then check if we have * now got all the responses we are looking for. if we have, we exit the * loop by setting the finish_up flag */ sent_all_requests = 0; i = 0; cursor = head; while(finish_up == 0) { while(sent_all_requests == 0) { if(send_echo_request(cursor) != 0) { return -1; } cursor->tx++; if(cursor->tx == count) { cursor = cursor->next; if(cursor == NULL) { sent_all_requests = 1; alarm(timeout); break; } } if(wait_between > 0) { gettimeofday(&wait_between_tv, &tz); timeval_add(&wait_between_tv, wait_between); break; } } while(time_to_send_request() == 0 && finish_up == 0) { if(recv_echo_responses() > 0) { if(got_all_responses() == 1) { finish_up = 1; } } } } /* * if we have been given a list of hosts to ping, we have to print out which * hosts did not give us a reply */ if(options & OPT_NLANR) { show_loss(); } return 0; }
int main(int argc, char *argv[]) { struct { struct kdbus_cmd_bus_make head; /* name item */ uint64_t n_size; uint64_t n_type; char name[64]; } __attribute__ ((__aligned__(8))) bus_make; int fdc, ret; char *bus; struct conn *conn_a; struct conn *conn_b; struct pollfd fds[2]; struct timeval start; unsigned int i; for (i = 0; i < sizeof(stress_payload); i++) stress_payload[i] = i; printf("-- opening /dev/kdbus/control\n"); fdc = open("/dev/kdbus/control", O_RDWR|O_CLOEXEC); if (fdc < 0) { fprintf(stderr, "--- error %d (%m)\n", fdc); return EXIT_FAILURE; } memset(&bus_make, 0, sizeof(bus_make)); bus_make.head.bloom_size = 64; snprintf(bus_make.name, sizeof(bus_make.name), "%u-testbus", getuid()); bus_make.n_type = KDBUS_ITEM_MAKE_NAME; bus_make.n_size = KDBUS_ITEM_HEADER_SIZE + strlen(bus_make.name) + 1; bus_make.head.size = sizeof(struct kdbus_cmd_bus_make) + bus_make.n_size; printf("-- creating bus '%s'\n", bus_make.name); ret = ioctl(fdc, KDBUS_CMD_BUS_MAKE, &bus_make); if (ret) { fprintf(stderr, "--- error %d (%m)\n", ret); return EXIT_FAILURE; } if (asprintf(&bus, "/dev/kdbus/%s/bus", bus_make.name) < 0) return EXIT_FAILURE; conn_a = connect_to_bus(bus); if (!conn_a) return EXIT_FAILURE; conn_b = connect_to_bus(bus); if (!conn_b) return EXIT_FAILURE; upload_policy(conn_a->fd, SERVICE_NAME); add_match_empty(conn_a->fd); add_match_empty(conn_b->fd); fds[0].fd = conn_a->fd; fds[1].fd = conn_b->fd; name_acquire(conn_a, SERVICE_NAME, 0); gettimeofday(&start, NULL); reset_stats(); ret = send_echo_request(conn_b, conn_a->id); if (ret) return EXIT_FAILURE; printf("-- entering poll loop ...\n"); while (1) { struct timeval now; unsigned int nfds = sizeof(fds) / sizeof(fds[0]); unsigned int i; for (i = 0; i < nfds; i++) { fds[i].events = POLLIN | POLLPRI | POLLHUP; fds[i].revents = 0; } ret = poll(fds, nfds, 10); if (ret < 0) break; if (fds[0].revents & POLLIN) { ret = handle_echo_reply(conn_a); if (ret) break; ret = send_echo_request(conn_b, conn_a->id); if (ret) break; } gettimeofday(&now, NULL); if (timeval_diff(&now, &start) / 1000ULL > 1000ULL) { start.tv_sec = now.tv_sec; start.tv_usec = now.tv_usec; dump_stats(); reset_stats(); } } printf("-- closing bus connections\n"); close(conn_a->fd); close(conn_b->fd); free(conn_a); free(conn_b); printf("-- closing bus master\n"); close(fdc); free(bus); return EXIT_SUCCESS; }
/* To determine the coordinates of the local node initially * Ping a subset of nodes and determine coordinates */ void init_coordinates(I3ServerList *list) { int n = MIN(NUM_LANDMARKS_COORDINATE, list->num_newservers + list->num_ping_list); I3ServerListNode *node = list->list, *temp_node; uint64_t start_time = wall_time(); Coordinates_RTT coord_rtt[NUM_LANDMARKS_COORDINATE]; int num_landmarks = 0; int started_full_list = 0; struct in_addr ia; nw_skt_t tmp_ping_sock; #ifdef ICMP_PING if (init_icmp_socket(&tmp_ping_sock) == -1) abort(); #else if (init_udp_socket(&tmp_ping_sock) == -1) abort(); #endif // wait for responses and accumulate // cut and pasted from below while ((wall_time() - start_time < COORD_INIT_PING_WAIT_TIME) && (num_landmarks < n)) { fd_set rset; struct timeval to; int ret; FD_ZERO(&rset); if (!node && !started_full_list) { node = list-> full_list; started_full_list = 1; } if (node) { ia.s_addr = htonl(node->addr); I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_VERBOSE, "Sending ICMP echo request to %s\n", inet_ntoa(ia)); #ifdef ICMP_PING send_echo_request(tmp_ping_sock, node->addr, 0); #else i3_echo_request(tmp_ping_sock, node->addr, node->port, 0); #endif node = node->next_list; } FD_SET(tmp_ping_sock, &rset); to.tv_sec = 0; to.tv_usec = 200000ULL; if ((ret = select(tmp_ping_sock+1, &rset, NULL, NULL, &to)) < 0) { int err = nw_error(); if (err == EINTR) continue; else { perror("select"); abort(); } } // message received on icmp socket if (FD_ISSET(tmp_ping_sock, &rset)) { uint32_t addr; uint16_t port, seq; uint64_t rtt; #ifdef ICMP_PING if (recv_echo_reply(tmp_ping_sock, &addr, &seq, &rtt)) { #else if (recv_i3_echo_reply(tmp_ping_sock, &addr, &port, &seq, &rtt)) { #endif temp_node = lookup_i3server(list, addr); assert(NULL != temp_node); coord_rtt[num_landmarks].coord = temp_node->coord; coord_rtt[num_landmarks].rtt = rtt; num_landmarks++; ia.s_addr = htonl(addr); I3_PRINT_DEBUG4(I3_DEBUG_LEVEL_VERBOSE, "Node: %s Coordinate: %.1f:%.1f RTT: %Ld\n", inet_ntoa(ia), temp_node->coord.latitude, temp_node->coord.longitude, rtt); } } } nw_close(tmp_ping_sock); // compute own coordinate compute_coordinates(num_landmarks, coord_rtt); } /* Update the coordinates of a node using ping information */ void update_coordinate(I3ServerList *list, I3ServerListNode *next_to_ping) { Coordinates_RTT coord_rtt[NUM_LANDMARKS_COORDINATE]; int count, num_landmarks = 0; I3ServerListNode *node; // n1 and n2: number of landmarks from ping_list and rest in // proportion to the number of nodes in those lists int i, n = MIN(NUM_LANDMARKS_COORDINATE, list->num_newservers + list->num_ping_list); int n1 = ((float)list->num_ping_list/ (list->num_newservers + list->num_ping_list)) * n; int n2 = n-n1; // add from ping list count = 0; for (i = 0, node = list->list; i < list->num_ping_list, count < n1; node = node->next_list, ++i) { if (node->n > 0) { coord_rtt[count].rtt = get_rtt_node(node); coord_rtt[count].coord = node->coord; count++; } } num_landmarks = count; // add from rest count = 0; for (i = 0, node = list->full_list; i < list->num_newservers, count < n2; node = node->next_list, ++i) { if (node->n > 0) { coord_rtt[num_landmarks + count].rtt = get_rtt_node(node); coord_rtt[num_landmarks + count].coord = node->coord; count++; } } num_landmarks += count; // recompute coordinates compute_coordinates(num_landmarks, coord_rtt); // repopulate ping list afresh change_ping_list(list, &next_to_ping, 1); }
void snmp_tunnel_ap_run(int tunnelfd,int trapfd) { struct pollfd fds[MAX_SNMP_MANAGERS + 2]; int num_fds = MAX_SNMP_MANAGERS + 2; char buffer[MAX_MSG_SIZE]; struct sockaddr_in snmpd_addr; int n_read,n_write; struct snmp_manager managers[MAX_SNMP_MANAGERS]; /* this is where the local snmpd agent listens */ bzero((char*)&snmpd_addr, sizeof(snmpd_addr)); snmpd_addr.sin_family = AF_INET; /* TODO : better define localhost here...? */ snmpd_addr.sin_addr.s_addr = htonl(INADDR_ANY); snmpd_addr.sin_port = htons(snmpd_port); /* prepare the sockets to be polled */ /* tunnel-side */ fds[0].fd = tunnelfd; fds[0].events = POLLIN | POLLHUP; /* prepare the sockets to be polled */ /* tunnel-side */ fds[1].fd = trapfd; fds[1].events = POLLIN | POLLHUP; /* initialize all manager structs. */ int i; for (i = 0; i < MAX_SNMP_MANAGERS ; i++){ managers[i].is_active = false; managers[i].pfd = &fds[i+2]; managers[i].pfd->fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); managers[i].pfd->events = POLLIN | POLLHUP; managers[i].last_active = 0; } int retval; int current_fd; tunnel_pkt_header * hdr; uint16_t type; int last_active = second_now(); for(;;){ retval = poll(fds, num_fds, AGENT_KEEPALIVE); if (retval == 0){ printf("sending ECHO_REQUEST\n"); send_echo_request(fds[0].fd); } else{ /* if something came from the tunnel, send it to snmpd */ if(fds[0].revents & POLLIN) { last_active = second_now(); memset(buffer,'\0', MAX_MSG_SIZE); n_read = recv(fds[0].fd, buffer, MAX_MSG_SIZE, 0); if(n_read <= 0){ printf("cannot read from socket - reconnecting...(%s)\n",strerror(errno)); break; } else { if(process_tunnel_packet(managers, buffer, snmpd_addr) != SUCCESS) { printf("failed to process packet from tunnel..."); // break; - no need to disconnect here... } } } /* forward snmp traps to the tunnel */ if(fds[1].revents & POLLIN) { if(forward_tunnel_trap_packet(fds[1].fd,fds[0].fd) != SUCCESS) { printf("Failed to forward trap to tunnel...\n"); break; } } /* if something came from snmpd, we need to multiplex and send to the tunnel */ for (i = 0; i < MAX_SNMP_MANAGERS ; i++) { if (managers[i].pfd->revents & POLLIN) { if(forward_tunnel_packet(managers[i],fds[0].fd) != SUCCESS) { printf("failed to forward to tunnel...\n"); break; } } } } /* check that the other end is still there... */ if ( (second_now() - last_active) > AGENT_TIMEOUT ) { printf("connection seems broken - reconnecting...\n"); break; } } printf("Exiting loop...\n"); /* close all sockets (tunnel + managers) */ for (i = 0; i < MAX_SNMP_MANAGERS + 1; i++){ close(fds[i].fd); } }