struct ether_header *uni_get_mac(int fd, char *ip, char *port) { char *buf, *p; ssize_t blen; #ifdef __APPLE__ ioctl(fd, BIOCGBLEN, &blen); #elif __linux__ blen = 1460; #endif buf = malloc(blen + 1); send_probe(ip, port); if (read(fd, buf, blen) < 0) die_with_signal("read"); #ifdef __APPLE__ struct bpf_hdr *bh = (struct bpf_hdr *)buf; p = buf + bh->bh_hdrlen; #elif __linux__ p = buf; #endif struct ether_header *eh = calloc(1, sizeof(*eh)); memcpy(eh, p, s_eth); memset(eh->ether_dhost, 0xff, ETH_ALEN); return eh; }
/*---------------------------------------------------------------------------*/ static void send_stream_probe(void *dummy) { /* Turn on the radio for sending a probe packet and anticipating a data packet from a neighbor. */ turn_radio_on(); /* Send a probe packet. */ send_probe(); is_streaming = 1; }
int traceroute_send_probe(struct traceroute *t, int ttl, int seq) { struct outdata *o = &t->outdata; /* Prepare outgoing data */ o->seq = seq; o->ttl = ttl; /* Avoid alignment problems by copying bytewise: */ (void)gettimeofday(&t->timesent, NULL); memcpy(&o->tv, t, sizeof(o->tv)); /* Finalize and send packet */ (*t->proto->prepare)(t, o); return send_probe(t, seq, ttl); }
int send_ra_solicit(int sock, uint8_t *buf) { int err; struct in6_addr addr; /* set receiver address */ inet_pton(AF_INET6, "ff02::02", &addr); /* build the message */ struct nd_router_solicit *solicit; solicit = (struct nd_router_solicit*)buf; solicit->nd_rs_type = ND_ROUTER_SOLICIT; solicit->nd_rs_code = 0; solicit->nd_rs_cksum = 0; solicit->nd_rs_reserved = 0; uint8_t *p = (uint8_t*)buf + sizeof(struct nd_router_solicit); err = send_probe(sock, buf, &addr, p - buf, 255); return err; }
int mmprobe_probe_V2(int id, void* data, int length, DataFormat_t* format_p){ int retval = 0; if (!probe_list_opened) { if (open_probe_list() < 0) return -1; } if ((id > MM_PROBE_NUMBER_OF_SPEECH_PROBES) || (probe_list[id-1] == 1)) { probe_t* p = create_probe(id); add_data_to_probe(p, data, length, format_p); retval = send_probe(p); delete_probe(p); } return retval; }
int queue_active_probe(int ifindex, __u32 addr) { static struct timeval prev; static int buckets; struct timeval now; gettimeofday(&now, NULL); if (prev.tv_sec) { int diff = (now.tv_sec-prev.tv_sec)*1000+(now.tv_usec-prev.tv_usec)/1000; buckets += diff; } else { buckets = broadcast_burst; } if (buckets > broadcast_burst) buckets = broadcast_burst; if (buckets >= broadcast_rate && !send_probe(ifindex, addr)) { buckets -= broadcast_rate; prev = now; return 0; } stats.probes_suppressed++; return -1; }
void *sendThread(void *p) { int i, j, n; // char _dest[MAXHOSTNAMELEN+1]; char _dest_ip[INET_ADDRSTRLEN+1]; struct sockaddr_in _destaddr; uchar o[4]; uint ip; uchar _seq; int rv; n = g_num_packets; /*num*/ ip = _startAddr.s_addr; for (i = 0; i < n; i++) { split_ip(ip,o); if (o[3] == 0) continue; if (!fBroadcastOk && (o[3] == 255)) continue; sprintf(_dest_ip,"%d.%d.%d.%d",o[0],o[1],o[2],o[3]); /* set _destaddr */ _destaddr.sin_family = AF_INET; _destaddr.sin_port = htons(g_port); if ( !inet_aton( _dest_ip, &_destaddr.sin_addr)) { printerr("inet_aton error %s\n",_dest_ip); continue; } for (j=0; j<g_repeat; j++) { /* send ping buffer */ _seq = 0; rv = send_probe(&_destaddr,_seq); g_npings++; if (fdebug) printerr("sendto[%d,%d] %s rv = %d\n", g_npings,_seq,_dest_ip,rv); if (rv < 0) { /*try to send again*/ rv = send_probe(&_destaddr,++_seq); if (rv < 0) { printerr("sendto[%d,%d] %s error %s\n", g_npings,_seq,_dest_ip,showlasterr()); continue; } } #ifdef NO_THREADS receiveThread(NULL); if (g_recv_status == 0 && !fBroadcastOk) { /* nothing returned, try again */ if (fping) { rv = send_poke1(&_destaddr); if (fdebug) printerr("sendto[%d,%d] %s poke rv = %d\n", g_npings,_seq,_dest_ip,rv); } rv = send_probe(&_destaddr,++_seq); if (fdebug) printerr("sendto[%d,%d] %s rv = %d\n", g_npings,_seq,_dest_ip,rv); if (rv >= 0) { receiveThread(NULL); } } #endif /* sleep an interval (g_delay usec) */ if (g_delay > 0) os_sleep(0,g_delay); } /*end-for g_repeat*/ ip++; /* increment to next IP */ } return(p); }
int main(int argc, char *argv[]) { int mib[4] = { CTL_NET, PF_INET6, IPPROTO_IPV6, IPV6CTL_DEFHLIM }; char hbuf[NI_MAXHOST], src0[NI_MAXHOST], *ep; int ch, i, on = 1, seq, rcvcmsglen, error, minlen; struct addrinfo hints, *res; static u_char *rcvcmsgbuf; u_long probe, hops, lport; struct hostent *hp; size_t size; uid_t uid; /* * Receive ICMP */ if ((rcvsock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) { perror("socket(ICMPv6)"); exit(5); } /* revoke privs */ uid = getuid(); if (setresuid(uid, uid, uid) == -1) err(1, "setresuid"); size = sizeof(i); (void) sysctl(mib, sizeof(mib)/sizeof(mib[0]), &i, &size, NULL, 0); max_hops = i; /* specify to tell receiving interface */ if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on)) < 0) err(1, "setsockopt(IPV6_RECVPKTINFO)"); /* specify to tell value of hoplimit field of received IP6 hdr */ if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on, sizeof(on)) < 0) err(1, "setsockopt(IPV6_RECVHOPLIMIT)"); seq = 0; while ((ch = getopt(argc, argv, "df:g:Ilm:np:q:rs:w:v")) != -1) switch (ch) { case 'd': options |= SO_DEBUG; break; case 'f': ep = NULL; errno = 0; first_hop = strtoul(optarg, &ep, 0); if (errno || !*optarg || *ep|| first_hop > 255) { fprintf(stderr, "traceroute6: invalid min hoplimit.\n"); exit(1); } break; case 'g': hp = getipnodebyname(optarg, AF_INET6, 0, &h_errno); if (hp == NULL) { fprintf(stderr, "traceroute6: unknown host %s\n", optarg); exit(1); } if (rth == NULL) { /* * XXX: We can't detect the number of * intermediate nodes yet. */ if ((rth = inet6_rth_init((void *)rtbuf, sizeof(rtbuf), IPV6_RTHDR_TYPE_0, 0)) == NULL) { fprintf(stderr, "inet6_rth_init failed.\n"); exit(1); } } if (inet6_rth_add((void *)rth, (struct in6_addr *)hp->h_addr)) { fprintf(stderr, "inet6_rth_add failed for %s\n", optarg); exit(1); } freehostent(hp); break; case 'I': useicmp++; ident = htons(getpid() & 0xffff); /* same as ping6 */ break; case 'l': lflag++; break; case 'm': ep = NULL; errno = 0; max_hops = strtoul(optarg, &ep, 0); if (errno || !*optarg || *ep || max_hops > 255) { fprintf(stderr, "traceroute6: invalid max hoplimit.\n"); exit(1); } break; case 'n': nflag++; break; case 'p': ep = NULL; errno = 0; lport = strtoul(optarg, &ep, 0); if (errno || !*optarg || *ep) { fprintf(stderr, "traceroute6: invalid port.\n"); exit(1); } if (lport == 0 || lport != (lport & 0xffff)) { fprintf(stderr, "traceroute6: port out of range.\n"); exit(1); } port = lport & 0xffff; break; case 'q': ep = NULL; errno = 0; nprobes = strtoul(optarg, &ep, 0); if (errno || !*optarg || *ep) { fprintf(stderr, "traceroute6: invalid nprobes.\n"); exit(1); } if (nprobes < 1) { fprintf(stderr, "traceroute6: nprobes must be >0.\n"); exit(1); } break; case 'r': options |= SO_DONTROUTE; break; case 's': /* * set the ip source address of the outbound * probe (e.g., on a multi-homed host). */ source = optarg; break; case 'v': verbose++; break; case 'w': ep = NULL; errno = 0; waittime = strtoul(optarg, &ep, 0); if (errno || !*optarg || *ep) { fprintf(stderr, "traceroute6: invalid wait time.\n"); exit(1); } if (waittime <= 1) { fprintf(stderr, "traceroute6: wait must be >1 sec.\n"); exit(1); } break; default: usage(); } argc -= optind; argv += optind; if (max_hops < first_hop) { fprintf(stderr, "traceroute6: max hoplimit must be larger than first hoplimit.\n"); exit(1); } if (argc < 1 || argc > 2) usage(); #if 1 setvbuf(stdout, NULL, _IOLBF, BUFSIZ); #else setlinebuf(stdout); #endif memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_INET6; hints.ai_socktype = SOCK_RAW; hints.ai_protocol = IPPROTO_ICMPV6; hints.ai_flags = AI_CANONNAME; error = getaddrinfo(*argv, NULL, &hints, &res); if (error) { fprintf(stderr, "traceroute6: %s\n", gai_strerror(error)); exit(1); } if (res->ai_addrlen != sizeof(Dst)) { fprintf(stderr, "traceroute6: size of sockaddr mismatch\n"); exit(1); } memcpy(&Dst, res->ai_addr, res->ai_addrlen); hostname = res->ai_canonname ? strdup(res->ai_canonname) : *argv; if (!hostname) { fprintf(stderr, "traceroute6: not enough core\n"); exit(1); } if (res->ai_next) { if (getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) strlcpy(hbuf, "?", sizeof(hbuf)); fprintf(stderr, "traceroute6: Warning: %s has multiple " "addresses; using %s\n", hostname, hbuf); } if (*++argv) { ep = NULL; errno = 0; datalen = strtoul(*argv, &ep, 0); if (errno || !*argv || *ep) { fprintf(stderr, "traceroute6: invalid packet length.\n"); exit(1); } } if (useicmp) minlen = ICMP6ECHOLEN + sizeof(struct tv32); else minlen = sizeof(struct opacket); if (datalen < minlen) datalen = minlen; else if (datalen >= MAXPACKET) { fprintf(stderr, "traceroute6: packet size must be %d <= s < %ld.\n", minlen, (long)MAXPACKET); exit(1); } outpacket = (struct opacket *)malloc((unsigned)datalen); if (!outpacket) { perror("malloc"); exit(1); } (void) bzero((char *)outpacket, datalen); /* initialize msghdr for receiving packets */ rcviov[0].iov_base = (caddr_t)packet; rcviov[0].iov_len = sizeof(packet); rcvmhdr.msg_name = (caddr_t)&Rcv; rcvmhdr.msg_namelen = sizeof(Rcv); rcvmhdr.msg_iov = rcviov; rcvmhdr.msg_iovlen = 1; rcvcmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(int)); if ((rcvcmsgbuf = malloc(rcvcmsglen)) == NULL) { fprintf(stderr, "traceroute6: malloc failed\n"); exit(1); } rcvmhdr.msg_control = (caddr_t) rcvcmsgbuf; rcvmhdr.msg_controllen = rcvcmsglen; if (options & SO_DEBUG) (void) setsockopt(rcvsock, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof(on)); if (options & SO_DONTROUTE) (void) setsockopt(rcvsock, SOL_SOCKET, SO_DONTROUTE, (char *)&on, sizeof(on)); /* * Send UDP or ICMP */ if (useicmp) { sndsock = rcvsock; } else { if ((sndsock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { perror("socket(SOCK_DGRAM)"); exit(5); } } #ifdef SO_SNDBUF i = datalen; if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&i, sizeof(i)) < 0) { perror("setsockopt(SO_SNDBUF)"); exit(6); } #endif /* SO_SNDBUF */ if (options & SO_DEBUG) (void) setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof(on)); if (options & SO_DONTROUTE) (void) setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, (char *)&on, sizeof(on)); if (rth) {/* XXX: there is no library to finalize the header... */ rth->ip6r_len = rth->ip6r_segleft * 2; if (setsockopt(sndsock, IPPROTO_IPV6, IPV6_RTHDR, (void *)rth, (rth->ip6r_len + 1) << 3)) { fprintf(stderr, "setsockopt(IPV6_RTHDR): %s\n", strerror(errno)); exit(1); } } /* * Source selection */ bzero(&Src, sizeof(Src)); if (source) { struct addrinfo hints, *res; int error; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_DGRAM; /*dummy*/ hints.ai_flags = AI_NUMERICHOST; error = getaddrinfo(source, "0", &hints, &res); if (error) { printf("traceroute6: %s: %s\n", source, gai_strerror(error)); exit(1); } if (res->ai_addrlen > sizeof(Src)) { printf("traceroute6: %s: %s\n", source, gai_strerror(error)); exit(1); } memcpy(&Src, res->ai_addr, res->ai_addrlen); freeaddrinfo(res); } else { struct sockaddr_in6 Nxt; int dummy; socklen_t len; Nxt = Dst; Nxt.sin6_port = htons(DUMMY_PORT); if (cmsg != NULL) bcopy(inet6_rthdr_getaddr(cmsg, 1), &Nxt.sin6_addr, sizeof(Nxt.sin6_addr)); if ((dummy = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { perror("socket"); exit(1); } if (connect(dummy, (struct sockaddr *)&Nxt, Nxt.sin6_len) < 0) { perror("connect"); exit(1); } len = sizeof(Src); if (getsockname(dummy, (struct sockaddr *)&Src, &len) < 0) { perror("getsockname"); exit(1); } if (getnameinfo((struct sockaddr *)&Src, Src.sin6_len, src0, sizeof(src0), NULL, 0, NI_NUMERICHOST)) { fprintf(stderr, "getnameinfo failed for source\n"); exit(1); } source = src0; close(dummy); } Src.sin6_port = htons(0); if (bind(sndsock, (struct sockaddr *)&Src, Src.sin6_len) < 0) { perror("bind"); exit(1); } { socklen_t len; len = sizeof(Src); if (getsockname(sndsock, (struct sockaddr *)&Src, &len) < 0) { perror("getsockname"); exit(1); } srcport = ntohs(Src.sin6_port); } /* * Message to users */ if (getnameinfo((struct sockaddr *)&Dst, Dst.sin6_len, hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST)) strlcpy(hbuf, "(invalid)", sizeof(hbuf)); fprintf(stderr, "traceroute6"); fprintf(stderr, " to %s (%s)", hostname, hbuf); if (source) fprintf(stderr, " from %s", source); fprintf(stderr, ", %lu hops max, %lu byte packets\n", max_hops, datalen); (void) fflush(stderr); if (first_hop > 1) printf("Skipping %lu intermediate hops\n", first_hop - 1); /* * Main loop */ for (hops = first_hop; hops <= max_hops; ++hops) { struct in6_addr lastaddr; int got_there = 0; int unreachable = 0; printf("%2lu ", hops); bzero(&lastaddr, sizeof(lastaddr)); for (probe = 0; probe < nprobes; ++probe) { int cc; struct timeval t1, t2; (void) gettimeofday(&t1, NULL); send_probe(++seq, hops); while ((cc = wait_for_reply(rcvsock, &rcvmhdr))) { (void) gettimeofday(&t2, NULL); if ((i = packet_ok(&rcvmhdr, cc, seq))) { if (!IN6_ARE_ADDR_EQUAL(&Rcv.sin6_addr, &lastaddr)) { print(&rcvmhdr, cc); lastaddr = Rcv.sin6_addr; } printf(" %g ms", deltaT(&t1, &t2)); switch (i - 1) { case ICMP6_DST_UNREACH_NOROUTE: ++unreachable; printf(" !N"); break; case ICMP6_DST_UNREACH_ADMIN: ++unreachable; printf(" !P"); break; case ICMP6_DST_UNREACH_NOTNEIGHBOR: ++unreachable; printf(" !S"); break; case ICMP6_DST_UNREACH_ADDR: ++unreachable; printf(" !A"); break; case ICMP6_DST_UNREACH_NOPORT: if (rcvhlim >= 0 && rcvhlim <= 1) printf(" !"); ++got_there; break; } break; } } if (cc == 0) printf(" *"); (void) fflush(stdout); } putchar('\n'); if (got_there || (unreachable > 0 && unreachable >= ((nprobes + 1) / 2))) { exit(0); } } exit(0); }
/* * pinger -- * Compose and transmit an ICMP ECHO REQUEST packet. The IP packet * will be added on by the kernel. The ID field is our UNIX process ID, * and the sequence number is an ascending integer. The first 8 bytes * of the data portion are used to hold a UNIX "timeval" struct in VAX * byte-order, to compute the round-trip time. */ int pinger(void) { static int oom_count; static int tokens; int i; /* Have we already sent enough? If we have, return an arbitrary positive value. */ if (exiting || (npackets && ntransmitted >= npackets && !deadline)) return 1000; /* Check that packets < rate*time + preload */ if (cur_time.tv_sec == 0) { gettimeofday(&cur_time, NULL); tokens = interval*(preload-1); } else { long ntokens; struct timeval tv; gettimeofday(&tv, NULL); ntokens = (tv.tv_sec - cur_time.tv_sec)*1000 + (tv.tv_usec-cur_time.tv_usec)/1000; if (!interval) { /* Case of unlimited flood is special; * if we see no reply, they are limited to 100pps */ if (ntokens < MININTERVAL && in_flight() >= preload) return MININTERVAL-ntokens; } ntokens += tokens; if (ntokens > interval*preload) ntokens = interval*preload; if (ntokens < interval) return interval - ntokens; cur_time = tv; tokens = ntokens - interval; } if (options & F_OUTSTANDING) { if (ntransmitted > 0 && !rcvd_test(ntransmitted)) { print_timestamp(); printf("no answer yet for icmp_seq=%lu\n", (ntransmitted % MAX_DUP_CHK)); fflush(stdout); } } resend: i = send_probe(); if (i == 0) { oom_count = 0; advance_ntransmitted(); if (!(options & F_QUIET) && (options & F_FLOOD)) { /* Very silly, but without this output with * high preload or pipe size is very confusing. */ if ((preload < screen_width && pipesize < screen_width) || in_flight() < screen_width) write_stdout(".", 1); } return interval - tokens; } /* And handle various errors... */ if (i > 0) { /* Apparently, it is some fatal bug. */ abort(); } else if (errno == ENOBUFS || errno == ENOMEM) { int nores_interval; /* Device queue overflow or OOM. Packet is not sent. */ tokens = 0; /* Slowdown. This works only in adaptive mode (option -A) */ rtt_addend += (rtt < 8*50000 ? rtt/8 : 50000); if (options&F_ADAPTIVE) update_interval(); nores_interval = SCHINT(interval/2); if (nores_interval > 500) nores_interval = 500; oom_count++; if (oom_count*nores_interval < lingertime) return nores_interval; i = 0; /* Fall to hard error. It is to avoid complete deadlock * on stuck output device even when dealine was not requested. * Expected timings are screwed up in any case, but we will * exit some day. :-) */ } else if (errno == EAGAIN) { /* Socket buffer is full. */ tokens += interval; return MININTERVAL; } else { if ((i=receive_error_msg()) > 0) { /* An ICMP error arrived. */ tokens += interval; return MININTERVAL; } /* Compatibility with old linuces. */ if (i == 0 && confirm_flag && errno == EINVAL) { confirm_flag = 0; errno = 0; } if (!errno) goto resend; } /* Hard local error. Pretend we sent packet. */ advance_ntransmitted(); if (i == 0 && !(options & F_QUIET)) { if (options & F_FLOOD) write_stdout("E", 1); else perror("ping: sendmsg"); } tokens = 0; return SCHINT(interval); }
/** * Read a packet from the underlying radio driver. If the incoming * packet is a probe packet and the sender of the probe matches the * destination address of the queued packet (if any), the queued packet * is sent. */ static void input_packet(void) { struct lpp_hdr hdr; clock_time_t reception_time; reception_time = clock_time(); if(!NETSTACK_FRAMER.parse()) { printf("lpp input_packet framer error\n"); } memcpy(&hdr, packetbuf_dataptr(), sizeof(struct lpp_hdr));; packetbuf_hdrreduce(sizeof(struct lpp_hdr)); /* PRINTF("got packet type %d\n", hdr->type);*/ if(hdr.type == TYPE_PROBE) { struct announcement_msg adata; /* Register the encounter with the sending node. We now know the neighbor's phase. */ register_encounter(&hdr.sender, reception_time); /* Parse incoming announcements */ memcpy(&adata, packetbuf_dataptr(), MIN(packetbuf_datalen(), sizeof(adata))); #if 0 PRINTF("%d.%d: probe from %d.%d with %d announcements\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], hdr.sender.u8[0], hdr.sender.u8[1], adata->num); if(adata.num / sizeof(struct announcement_data) > sizeof(struct announcement_msg)) { /* Sanity check. The number of announcements is too large - corrupt packet has been received. */ return 0; } for(i = 0; i < adata.num; ++i) { /* PRINTF("%d.%d: announcement %d: %d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], adata->data[i].id, adata->data[i].value);*/ announcement_heard(&hdr.sender, adata.data[i].id, adata.data[i].value); } #endif /* 0 */ /* Go through the list of packets to be sent to see if any of them match the sender of the probe, or if they are a broadcast packet that should be sent. */ if(list_length(queued_packets_list) > 0) { struct queue_list_item *i; for(i = list_head(queued_packets_list); i != NULL; i = list_item_next(i)) { const rimeaddr_t *receiver; uint8_t sent; sent = 0; receiver = queuebuf_addr(i->packet, PACKETBUF_ADDR_RECEIVER); if(rimeaddr_cmp(receiver, &hdr.sender) || rimeaddr_cmp(receiver, &rimeaddr_null)) { queuebuf_to_packetbuf(i->packet); #if WITH_PENDING_BROADCAST if(i->broadcast_flag == BROADCAST_FLAG_NONE || i->broadcast_flag == BROADCAST_FLAG_SEND) { i->num_transmissions = 1; NETSTACK_RADIO.send(queuebuf_dataptr(i->packet), queuebuf_datalen(i->packet)); sent = 1; PRINTF("%d.%d: got a probe from %d.%d, sent packet to %d.%d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], hdr.sender.u8[0], hdr.sender.u8[1], receiver->u8[0], receiver->u8[1]); } else { PRINTF("%d.%d: got a probe from %d.%d, did not send packet\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], hdr.sender.u8[0], hdr.sender.u8[1]); } #else /* WITH_PENDING_BROADCAST */ i->num_transmissions = 1; NETSTACK_RADIO.send(queuebuf_dataptr(i->packet), queuebuf_datalen(i->packet)); PRINTF("%d.%d: got a probe from %d.%d, sent packet to %d.%d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], hdr.sender.u8[0], hdr.sender.u8[1], receiver->u8[0], receiver->u8[1]); #endif /* WITH_PENDING_BROADCAST */ /* off();*/ /* Attribute the energy spent on listening for the probe to this packet transmission. */ compower_accumulate(&i->compower); /* If the packet was not a broadcast packet, we dequeue it now. Broadcast packets should be transmitted to all neighbors, and are dequeued by the dutycycling function instead, after the appropriate time. */ if(!rimeaddr_cmp(receiver, &rimeaddr_null)) { if(detect_ack()) { remove_queued_packet(i, 1); } else { remove_queued_packet(i, 0); } #if WITH_PROBE_AFTER_TRANSMISSION /* Send a probe packet to catch any reply from the other node. */ restart_dutycycle(PROBE_AFTER_TRANSMISSION_TIME); #endif /* WITH_PROBE_AFTER_TRANSMISSION */ #if WITH_STREAMING if(is_streaming) { ctimer_set(&stream_probe_timer, STREAM_PROBE_TIME, send_stream_probe, NULL); } #endif /* WITH_STREAMING */ } if(sent) { turn_radio_off(); } #if WITH_ACK_OPTIMIZATION if(packetbuf_attr(PACKETBUF_ATTR_RELIABLE) || packetbuf_attr(PACKETBUF_ATTR_ERELIABLE)) { /* We're sending a packet that needs an ACK, so we keep the radio on in anticipation of the ACK. */ turn_radio_on(); } #endif /* WITH_ACK_OPTIMIZATION */ } } } } else if(hdr.type == TYPE_DATA) { turn_radio_off(); if(!rimeaddr_cmp(&hdr.receiver, &rimeaddr_null)) { if(!rimeaddr_cmp(&hdr.receiver, &rimeaddr_node_addr)) { /* Not broadcast or for us */ PRINTF("%d.%d: data not for us from %d.%d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], hdr.sender.u8[0], hdr.sender.u8[1]); return; } packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &hdr.receiver); } packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &hdr.sender); PRINTF("%d.%d: got data from %d.%d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], hdr.sender.u8[0], hdr.sender.u8[1]); /* Accumulate the power consumption for the packet reception. */ compower_accumulate(¤t_packet); /* Convert the accumulated power consumption for the received packet to packet attributes so that the higher levels can keep track of the amount of energy spent on receiving the packet. */ compower_attrconv(¤t_packet); /* Clear the accumulated power consumption so that it is ready for the next packet. */ compower_clear(¤t_packet); #if WITH_PENDING_BROADCAST if(rimeaddr_cmp(&hdr.receiver, &rimeaddr_null)) { /* This is a broadcast packet. Check the list of pending packets to see if we are currently sending a broadcast. If so, we refrain from sending our broadcast until one sleep cycle period, so that the other broadcaster will have finished sending. */ struct queue_list_item *i; for(i = list_head(queued_packets_list); i != NULL; i = list_item_next(i)) { /* If the packet is a broadcast packet that is not yet ready to be sent, we do not send it. */ if(i->broadcast_flag == BROADCAST_FLAG_PENDING) { PRINTF("Someone else is sending, pending -> waiting\n"); set_broadcast_flag(i, BROADCAST_FLAG_WAITING); } } } #endif /* WITH_PENDING_BROADCAST */ #if WITH_PROBE_AFTER_RECEPTION /* XXX send probe after receiving a packet to facilitate data streaming. We must first copy the contents of the packetbuf into a queuebuf to avoid overwriting the data with the probe packet. */ if(rimeaddr_cmp(&hdr.receiver, &rimeaddr_node_addr)) { struct queuebuf *q; q = queuebuf_new_from_packetbuf(); if(q != NULL) { send_probe(); queuebuf_to_packetbuf(q); queuebuf_free(q); } } #endif /* WITH_PROBE_AFTER_RECEPTION */ #if WITH_ADAPTIVE_OFF_TIME off_time = LOWEST_OFF_TIME; restart_dutycycle(off_time); #endif /* WITH_ADAPTIVE_OFF_TIME */ NETSTACK_MAC.input(); } }
/** * Duty cycle the radio and send probes. This function is called * repeatedly by a ctimer. The function restart_dutycycle() is used to * (re)start the duty cycling. */ static int dutycycle(void *ptr) { struct ctimer *t = ptr; PT_BEGIN(&dutycycle_pt); while(1) { #if WITH_PENDING_BROADCAST { /* Before sending the probe, we mark all broadcast packets in our output queue to be pending. This means that they are ready to be sent, once we know that no neighbor is currently broadcasting. */ for(p = list_head(queued_packets_list); p != NULL; p = list_item_next(p)) { if(p->broadcast_flag == BROADCAST_FLAG_WAITING) { PRINTF("wait -> pending\n"); set_broadcast_flag(p, BROADCAST_FLAG_PENDING); } } } #endif /* WITH_PENDING_BROADCAST */ /* Turn on the radio for sending a probe packet and anticipating a data packet from a neighbor. */ turn_radio_on(); /* Send a probe packet. */ send_probe(); /* Set a timer so that we keep the radio on for LISTEN_TIME. */ ctimer_set(t, LISTEN_TIME, (void (*)(void *))dutycycle, t); PT_YIELD(&dutycycle_pt); #if WITH_PENDING_BROADCAST { struct queue_list_item *p; /* Go through the list of packets we are waiting to send, and check if there are any pending broadcasts in the list. If there are pending broadcasts, and we did not receive any broadcast packets from a neighbor in response to our probe, we mark the broadcasts as being ready to send. */ for(p = list_head(queued_packets_list); p != NULL; p = list_item_next(p)) { if(p->broadcast_flag == BROADCAST_FLAG_PENDING) { PRINTF("pending -> send\n"); set_broadcast_flag(p, BROADCAST_FLAG_SEND); turn_radio_on(); } } } #endif /* WITH_PENDING_BROADCAST */ /* If we have no packets to send (indicated by the list length of queued_packets_list being zero), we should turn the radio off. Othersize, we keep the radio on. */ if(num_packets_to_send() == 0) { /* If we are not listening for announcements, we turn the radio off and wait until we send the next probe. */ if(is_listening == 0) { int current_off_time; if(!NETSTACK_RADIO.receiving_packet()) { turn_radio_off(); compower_accumulate(&compower_idle_activity); } current_off_time = off_time - off_time_adjustment; if(current_off_time < LISTEN_TIME * 2) { current_off_time = LISTEN_TIME * 2; } off_time_adjustment = 0; ctimer_set(t, current_off_time, (void (*)(void *))dutycycle, t); PT_YIELD(&dutycycle_pt); #if WITH_ADAPTIVE_OFF_TIME off_time += LOWEST_OFF_TIME; if(off_time > OFF_TIME) { off_time = OFF_TIME; } #endif /* WITH_ADAPTIVE_OFF_TIME */ } else { /* We are listening for annonucements, so we count down the listen time, and keep the radio on. */ is_listening--; ctimer_set(t, OFF_TIME, (void (*)(void *))dutycycle, t); PT_YIELD(&dutycycle_pt); } } else { /* We had pending packets to send, so we do not turn the radio off. */ ctimer_set(t, off_time, (void (*)(void *))dutycycle, t); PT_YIELD(&dutycycle_pt); } } PT_END(&dutycycle_pt); }
traceroute_main(int argc, char *argv[]) #endif { extern char *optarg; extern int optind; struct hostent *hp; struct sockaddr_in from, *to; int ch, i, on, probe, seq, tos, ttl; int options = 0; /* socket options */ char *source = 0; int nprobes = 3; on = 1; seq = tos = 0; to = (struct sockaddr_in *)&whereto; while ((ch = getopt(argc, argv, "dm:np:q:rs:t:w:v")) != EOF) switch(ch) { case 'd': #ifdef CONFIG_FEATURE_TRACEROUTE_SO_DEBUG options |= SO_DEBUG; #endif break; case 'm': max_ttl = atoi(optarg); if (max_ttl <= 1) bb_error_msg_and_die("max ttl must be >1."); break; case 'n': nflag++; break; case 'p': port = atoi(optarg); if (port < 1) bb_error_msg_and_die("port must be >0."); break; case 'q': nprobes = atoi(optarg); if (nprobes < 1) bb_error_msg_and_die("nprobes must be >0."); break; case 'r': options |= SO_DONTROUTE; break; case 's': /* * set the ip source address of the outbound * probe (e.g., on a multi-homed host). */ source = optarg; break; case 't': tos = atoi(optarg); if (tos < 0 || tos > 255) bb_error_msg_and_die("tos must be 0 to 255."); break; case 'v': #ifdef CONFIG_FEATURE_TRACEROUTE_VERBOSE verbose++; #endif break; case 'w': waittime = atoi(optarg); if (waittime <= 1) bb_error_msg_and_die("wait must be >1 sec."); break; default: bb_show_usage(); } argc -= optind; argv += optind; if (argc < 1) bb_show_usage(); setlinebuf (stdout); memset(&whereto, 0, sizeof(struct sockaddr)); hp = xgethostbyname(*argv); to->sin_family = hp->h_addrtype; memcpy(&to->sin_addr, hp->h_addr, hp->h_length); hostname = (char *)hp->h_name; if (*++argv) datalen = atoi(*argv); if (datalen < 0 || datalen >= MAXPACKET - sizeof(struct opacket)) bb_error_msg_and_die("packet size must be 0 <= s < %d.", MAXPACKET - sizeof(struct opacket)); datalen += sizeof(struct opacket); outpacket = (struct opacket *)xmalloc((unsigned)datalen); memset(outpacket, 0, datalen); outpacket->ip.ip_dst = to->sin_addr; outpacket->ip.ip_tos = tos; outpacket->ip.ip_v = IPVERSION; outpacket->ip.ip_id = 0; ident = (getpid() & 0xffff) | 0x8000; if ((sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) bb_perror_msg_and_die(bb_msg_can_not_create_raw_socket); s = create_icmp_socket(); #ifdef CONFIG_FEATURE_TRACEROUTE_SO_DEBUG if (options & SO_DEBUG) (void) setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof(on)); #endif if (options & SO_DONTROUTE) (void) setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&on, sizeof(on)); #ifdef SO_SNDBUF if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&datalen, sizeof(datalen)) < 0) bb_perror_msg_and_die("SO_SNDBUF"); #endif #ifdef IP_HDRINCL if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, (char *)&on, sizeof(on)) < 0) bb_perror_msg_and_die("IP_HDRINCL"); #endif #ifdef CONFIG_FEATURE_TRACEROUTE_SO_DEBUG if (options & SO_DEBUG) (void) setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof(on)); #endif if (options & SO_DONTROUTE) (void) setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, (char *)&on, sizeof(on)); if (source) { memset(&from, 0, sizeof(struct sockaddr)); from.sin_family = AF_INET; from.sin_addr.s_addr = inet_addr(source); if (from.sin_addr.s_addr == -1) bb_error_msg_and_die("unknown host %s", source); outpacket->ip.ip_src = from.sin_addr; #ifndef IP_HDRINCL if (bind(sndsock, (struct sockaddr *)&from, sizeof(from)) < 0) bb_perror_msg_and_die("bind"); #endif } fprintf(stderr, "traceroute to %s (%s)", hostname, inet_ntoa(to->sin_addr)); if (source) fprintf(stderr, " from %s", source); fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, datalen); for (ttl = 1; ttl <= max_ttl; ++ttl) { u_long lastaddr = 0; int got_there = 0; int unreachable = 0; printf("%2d ", ttl); for (probe = 0; probe < nprobes; ++probe) { int cc, reset_timer; struct timeval t1, t2; struct timezone tz; struct ip *ip; (void) gettimeofday(&t1, &tz); send_probe(++seq, ttl); reset_timer = 1; while ((cc = wait_for_reply(s, &from, reset_timer)) != 0) { (void) gettimeofday(&t2, &tz); if ((i = packet_ok(packet, cc, &from, seq))) { reset_timer = 1; if (from.sin_addr.s_addr != lastaddr) { print(packet, cc, &from); lastaddr = from.sin_addr.s_addr; } printf(" %g ms", deltaT(&t1, &t2)); switch(i - 1) { case ICMP_UNREACH_PORT: ip = (struct ip *)packet; if (ip->ip_ttl <= 1) printf(" !"); ++got_there; break; case ICMP_UNREACH_NET: ++unreachable; printf(" !N"); break; case ICMP_UNREACH_HOST: ++unreachable; printf(" !H"); break; case ICMP_UNREACH_PROTOCOL: ++got_there; printf(" !P"); break; case ICMP_UNREACH_NEEDFRAG: ++unreachable; printf(" !F"); break; case ICMP_UNREACH_SRCFAIL: ++unreachable; printf(" !S"); break; } break; } else reset_timer = 0; } if (cc == 0) printf(" *"); (void) fflush(stdout); } putchar('\n'); if (got_there || unreachable >= nprobes-1) return 0; } return 0; }
int main(int argc, char *argv[]) { char pa[MAXHOSTNAMELEN]; extern char *optarg; extern int optind; struct hostent *hp; struct sockaddr_in6 from, *to; int ch, i, on, probe, seq, tos, ttl; int socket_errno; icmp_sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); socket_errno = errno; if (setuid(getuid())) { perror("traceroute6: setuid"); exit(-1); } on = 1; seq = tos = 0; to = (struct sockaddr_in6 *)&whereto; while ((ch = getopt(argc, argv, "dm:np:q:rs:t:w:vi:g:V")) != EOF) { switch(ch) { case 'd': options |= SO_DEBUG; break; case 'm': max_ttl = atoi(optarg); if (max_ttl <= 1) { Fprintf(stderr, "traceroute: max ttl must be >1.\n"); exit(1); } break; case 'n': nflag++; break; case 'p': port = atoi(optarg); if (port < 1) { Fprintf(stderr, "traceroute: port must be >0.\n"); exit(1); } break; case 'q': nprobes = atoi(optarg); if (nprobes < 1) { Fprintf(stderr, "traceroute: nprobes must be >0.\n"); exit(1); } break; case 'r': options |= SO_DONTROUTE; break; case 's': /* * set the ip source address of the outbound * probe (e.g., on a multi-homed host). */ source = optarg; break; case 'i': device = optarg; break; case 'g': Fprintf(stderr, "Sorry, rthdr is not yet supported\n"); break; case 'v': verbose++; break; case 'w': waittime = atoi(optarg); if (waittime <= 1) { Fprintf(stderr, "traceroute: wait must be >1 sec.\n"); exit(1); } break; case 'V': printf("traceroute6 utility, iputils-ss%s\n", SNAPSHOT); exit(0); default: usage(); } } argc -= optind; argv += optind; if (argc < 1) usage(); setlinebuf (stdout); (void) bzero((char *)&whereto, sizeof(whereto)); to->sin6_family = AF_INET6; to->sin6_port = htons(port); if (inet_pton(AF_INET6, *argv, &to->sin6_addr) > 0) { hostname = *argv; } else { hp = gethostbyname2(*argv, AF_INET6); if (hp) { memmove((caddr_t)&to->sin6_addr, hp->h_addr, sizeof(to->sin6_addr)); hostname = (char *)hp->h_name; } else { (void)fprintf(stderr, "traceroute: unknown host %s\n", *argv); exit(1); } } firsthop = *to; if (*++argv) { datalen = atoi(*argv); /* Message for rpm maintainers: have _shame_. If you want * to fix something send the patch to me for sanity checking. * "datalen" patch is a shit. */ if (datalen == 0) datalen = sizeof(struct pkt_format); else if (datalen < (int)sizeof(struct pkt_format) || datalen >= MAXPACKET) { Fprintf(stderr, "traceroute: packet size must be %d <= s < %d.\n", (int)sizeof(struct pkt_format), MAXPACKET); exit(1); } } ident = getpid(); sendbuff = malloc(datalen); if (sendbuff == NULL) { fprintf(stderr, "malloc failed\n"); exit(1); } if (icmp_sock < 0) { errno = socket_errno; perror("traceroute6: icmp socket"); exit(1); } #ifdef IPV6_RECVPKTINFO setsockopt(icmp_sock, SOL_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on)); setsockopt(icmp_sock, SOL_IPV6, IPV6_2292PKTINFO, &on, sizeof(on)); #else setsockopt(icmp_sock, SOL_IPV6, IPV6_PKTINFO, &on, sizeof(on)); #endif if (options & SO_DEBUG) setsockopt(icmp_sock, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof(on)); if (options & SO_DONTROUTE) setsockopt(icmp_sock, SOL_SOCKET, SO_DONTROUTE, (char *)&on, sizeof(on)); on = 2; if (setsockopt(icmp_sock, SOL_RAW, IPV6_CHECKSUM, &on, sizeof(on)) < 0) { perror("setsockopt(RAW_CHECKSUM)"); exit(2); } if ((sndsock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { perror("traceroute: UDP socket"); exit(5); } #ifdef SO_SNDBUF if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&datalen, sizeof(datalen)) < 0) { perror("traceroute: SO_SNDBUF"); exit(6); } #endif /* SO_SNDBUF */ if (options & SO_DEBUG) (void) setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof(on)); if (options & SO_DONTROUTE) (void) setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, (char *)&on, sizeof(on)); if (source == NULL) { socklen_t alen; int probe_fd = socket(AF_INET6, SOCK_DGRAM, 0); if (probe_fd < 0) { perror("socket"); exit(1); } if (device) { if (setsockopt(probe_fd, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device)+1) == -1) perror("WARNING: interface is ignored"); } firsthop.sin6_port = htons(1025); if (connect(probe_fd, (struct sockaddr*)&firsthop, sizeof(firsthop)) == -1) { perror("connect"); exit(1); } alen = sizeof(saddr); if (getsockname(probe_fd, (struct sockaddr*)&saddr, &alen) == -1) { perror("getsockname"); exit(1); } saddr.sin6_port = 0; close(probe_fd); } else { (void) bzero((char *)&saddr, sizeof(saddr)); saddr.sin6_family = AF_INET6; if (inet_pton(AF_INET6, source, &saddr.sin6_addr) <= 0) { Printf("traceroute: unknown addr %s\n", source); exit(1); } } if (bind(sndsock, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) { perror ("traceroute: bind sending socket"); exit (1); } if (bind(icmp_sock, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) { perror ("traceroute: bind icmp6 socket"); exit (1); } Fprintf(stderr, "traceroute to %s (%s)", hostname, inet_ntop(AF_INET6, &to->sin6_addr, pa, sizeof(pa))); Fprintf(stderr, " from %s", inet_ntop(AF_INET6, &saddr.sin6_addr, pa, sizeof(pa))); Fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, datalen); (void) fflush(stderr); for (ttl = 1; ttl <= max_ttl; ++ttl) { struct in6_addr lastaddr = {{{0,}}}; int got_there = 0; int unreachable = 0; Printf("%2d ", ttl); for (probe = 0; probe < nprobes; ++probe) { int cc, reset_timer; struct timeval t1, t2; struct timezone tz; struct in6_addr to; gettimeofday(&t1, &tz); send_probe(++seq, ttl); reset_timer = 1; while ((cc = wait_for_reply(icmp_sock, &from, &to, reset_timer)) != 0) { gettimeofday(&t2, &tz); if ((i = packet_ok(packet, cc, &from, &to, seq, &t1))) { reset_timer = 1; if (memcmp(&from.sin6_addr, &lastaddr, sizeof(from.sin6_addr))) { print(packet, cc, &from); memcpy(&lastaddr, &from.sin6_addr, sizeof(lastaddr)); } Printf(" %g ms", deltaT(&t1, &t2)); switch(i - 1) { case ICMP6_DST_UNREACH_NOPORT: ++got_there; break; case ICMP6_DST_UNREACH_NOROUTE: ++unreachable; Printf(" !N"); break; case ICMP6_DST_UNREACH_ADDR: ++unreachable; Printf(" !H"); break; case ICMP6_DST_UNREACH_ADMIN: ++unreachable; Printf(" !S"); break; } break; } else reset_timer = 0; } if (cc <= 0) Printf(" *"); (void) fflush(stdout); } putchar('\n'); if (got_there || (unreachable > 0 && unreachable >= nprobes-1)) exit(0); } return 0; }
void aodv(void) { //The queue holding all the events to be dealt with task *tmp_task; //Initalize the variables init_waitqueue_head(&aodv_wait); atomic_set(&kill_thread, 0); atomic_set(&aodv_is_dead, 0); //Name our thread /*lock_kernel(); sprintk(current->comm, "aodv-mcc"); //exit_mm(current); --> equivale a: current->mm = NULL; //we are in a kthread? aren't we? unlock_kernel();*/ //add_wait_queue_exclusive(event_socket->sk->sleep,&(aodv_wait)); // add_wait_queue(&(aodv_wait),event_socket->sk->sleep); //why would I ever want to stop ? :) for (;;) { //should the thread exit? if (atomic_read(&kill_thread)) { goto exit; } //goto sleep until we recieve an interupt interruptible_sleep_on(&aodv_wait); //should the thread exit? if (atomic_read(&kill_thread)) { goto exit; } //While the buffer is not empty extern dtn_hello_ip; while ((tmp_task = get_task()) != NULL) { u_int32_t dst; //takes a different action depending on what type of event is recieved switch (tmp_task->type) { //remove following case when DTN hell test end case TASK_DTN_HELLO: //inet_aton("127.127.127.127",&dst); //extern u_int32_t dtn_hello_ip; gen_rreq(g_mesh_ip,dtn_hello_ip,tmp_task->tos); #ifdef CaiDebug printk("-------DTN HELLO TASK---------\n"); #endif //insert_timer_simple(TASK_DTN_HELLO, 300*HELLO_INTERVAL, g_mesh_ip); //update_timer_queue(); break; //RREP case TASK_RECV_RREP: recv_rrep(tmp_task); kfree(tmp_task->data); break; //RERR case TASK_RECV_RERR: //printk("-----------\nget RERR from %s----------\n",inet_ntoa(tmp_task->src_ip)); recv_rerr(tmp_task); kfree(tmp_task->data); break; case TASK_RECV_HELLO: //printk("get HELLO from %s\n",inet_ntoa(tmp_task->src_ip)); recv_hello(tmp_task); kfree(tmp_task->data); break; /****************添加接收到通路包的任务***************/ #ifdef RECOVERYPATH case TASK_RECV_RCVP: //printk("Receive a RCVP\n"); recv_rcvp(tmp_task); kfree(tmp_task->data); break; case TASK_RECV_RRDP: //printk("Receive a RRDP\n"); recv_rrdp(tmp_task); kfree(tmp_task->data); break; #endif //Cleanup the Route Table and Flood ID queue case TASK_CLEANUP: flush_aodv_route_table(); break; case TASK_HELLO: //printk("gen HELLO\n"); gen_hello(); break; case TASK_ST: gen_st_rreq(); break; case TASK_GW_CLEANUP: update_gw_lifetimes(); insert_timer_simple(TASK_GW_CLEANUP, ACTIVE_GWROUTE_TIMEOUT, g_mesh_ip); update_timer_queue(); break; case TASK_NEIGHBOR: //printk("get NEIGHBOR TASH,delete neigh %s\n",inet_ntoa(tmp_task->src_ip)); delete_aodv_neigh(tmp_task->src_ip); break; case TASK_ROUTE_CLEANUP: flush_aodv_route_table(); break; case TASK_SEND_ETT: send_probe(tmp_task->dst_ip); break; //A small probe packet is received case TASK_RECV_S_ETT: recv_sprobe(tmp_task); kfree(tmp_task->data); break; //A large probe packet is received case TASK_RECV_L_ETT: recv_lprobe(tmp_task); kfree(tmp_task->data); break; case TASK_ETT_CLEANUP: reset_ett(find_aodv_neigh(tmp_task->src_ip)); printk("Reseting ETT-Info from neighbour %s\n", inet_ntoa(tmp_task->src_ip)); break; case TASK_NEIGHBOR_2H: delete_aodv_neigh_2h(tmp_task->src_ip); break; case TASK_RECV_RREQ: recv_rreq(tmp_task); kfree(tmp_task->data); break; case TASK_RESEND_RREQ: resend_rreq(tmp_task); break; case TASK_ETT_INFO: recv_ett_info(tmp_task); kfree(tmp_task->data); break; case TASK_SEND_RREP: gen_rrep(tmp_task->src_ip, tmp_task->dst_ip, tmp_task->tos); break; case TASK_RECV_STRREQ: recv_rreq_st(tmp_task); kfree(tmp_task->data); break; case TASK_UPDATE_LOAD: update_my_load(); break; case TASK_GEN_RREQ: gen_rreq(tmp_task->src_ip, tmp_task->dst_ip, tmp_task->tos); break; default: break; } kfree(tmp_task); } } exit: //Set the flag that shows you are dead atomic_set(&aodv_is_dead, 1); }
static void /* not inline */ send_probe(int seq, int ttl) { struct opacket *op = outpacket; struct ip *ip = &op->ip; struct udphdr *up = &op->udp; int i; struct timezone tz; #if defined (DMP_TRACEROUTE_1) int dataSize = datalen -12; /* Minus some parameters' length in struct opacket*/ #endif ip->ip_off = 0; ip->ip_hl = sizeof(*ip) >> 2; ip->ip_p = IPPROTO_UDP; #if defined (DMP_TRACEROUTE_1) ip->ip_len = dataSize; #else ip->ip_len = datalen; #endif ip->ip_ttl = ttl; ip->ip_v = IPVERSION; ip->ip_id = htons(ident+seq); up->source = htons(ident); up->dest = htons(port+seq); #if defined (DMP_TRACEROUTE_1) up->len = htons((u_short)(dataSize - sizeof(struct ip))); #else up->len = htons((u_short)(datalen - sizeof(struct ip))); #endif up->check = 0; op->seq = seq; op->ttl = ttl; (void) gettimeofday(&op->tv, &tz); #if defined (DMP_TRACEROUTE_1) i = sendto(sndsock, (char *)outpacket, dataSize, 0, &whereto, sizeof(struct sockaddr)); #else i = sendto(sndsock, (char *)outpacket, datalen, 0, &whereto, sizeof(struct sockaddr)); #endif #if defined (DMP_TRACEROUTE_1) if (i < 0 || i != dataSize) { #else if (i < 0 || i != datalen) { #endif if (i<0) perror("sendto"); #if defined (DMP_TRACEROUTE_1) printf("traceroute: wrote %s %d chars, ret=%d\n", hostname, dataSize, i); #else printf("traceroute: wrote %s %d chars, ret=%d\n", hostname, datalen, i); #endif (void) fflush(stdout); } } int #ifndef CONFIG_TRACEROUTE main(int argc, char *argv[]) #else traceroute_main(int argc, char *argv[]) #endif { extern char *optarg; extern int optind; struct hostent *hp; struct sockaddr_in from, *to; int ch, i, on, probe, seq, tos, ttl; int options = 0; /* socket options */ char *source = 0; int nprobes = 3; #if defined(AEI_VDSL_CUSTOMER_QWEST_Q2000) int ttl_set_flag = 0; #endif #if defined(AEI_VDSL_CUSTOMER_NCS) int failcount = 0; #endif #if defined(DMP_TRACEROUTE_1) unsigned int repTime; char strRepTime[16]; TraceRouteDataMsgBody traceRouteInfo; memset(&traceRouteInfo, 0 , sizeof(TraceRouteDataMsgBody)); TraceRouteDataMsgBody *pTraceRouteInfo = &traceRouteInfo; cmsMsg_init(EID_TRACEROUTE, &msgHandle); #endif on = 1; seq = tos = 0; to = (struct sockaddr_in *)&whereto; while ((ch = getopt(argc, argv, "dm:np:q:rs:t:w:v")) != EOF) switch(ch) { case 'd': #ifdef CONFIG_FEATURE_TRACEROUTE_SO_DEBUG options |= SO_DEBUG; #endif break; case 'm': max_ttl = atoi(optarg); #if defined(AEI_VDSL_CUSTOMER_QWEST_Q2000) ttl_set_flag = 1; #endif if (max_ttl <= 1) bb_error_msg_and_die("max ttl must be >1."); break; case 'n': nflag++; break; case 'p': port = atoi(optarg); if (port < 1) bb_error_msg_and_die("port must be >0."); break; case 'q': nprobes = atoi(optarg); if (nprobes < 1) bb_error_msg_and_die("nprobes must be >0."); break; case 'r': options |= SO_DONTROUTE; break; case 's': /* * set the ip source address of the outbound * probe (e.g., on a multi-homed host). */ source = optarg; break; case 't': tos = atoi(optarg); if (tos < 0 || tos > 255) bb_error_msg_and_die("tos must be 0 to 255."); break; case 'v': #ifdef CONFIG_FEATURE_TRACEROUTE_VERBOSE verbose++; #endif break; case 'w': waittime = atoi(optarg); if (waittime <= 1) bb_error_msg_and_die("wait must be >1 sec."); break; default: bb_show_usage(); } argc -= optind; argv += optind; if (argc < 1) bb_show_usage(); setlinebuf (stdout); memset(&whereto, 0, sizeof(struct sockaddr)); #if defined(DMP_TRACEROUTE_1) hp = gethostbyname(*argv); if (*++argv) { requesterId = atoi(*argv); } if (hp == NULL) { AEI_sendTraceRouteEventMessage(pTraceRouteInfo, Error_CannotResolveHostName); bb_herror_msg_and_die("%s", *--argv); } #else hp = xgethostbyname(*argv); #endif to->sin_family = hp->h_addrtype; memcpy(&to->sin_addr, hp->h_addr, hp->h_length); hostname = (char *)hp->h_name; if (*++argv) datalen = atoi(*argv); #if defined (DMP_TRACEROUTE_1) if (datalen == 0) { datalen = 40; /*Default data length*/ } #endif if (datalen < 0 || datalen >= MAXPACKET - sizeof(struct opacket)) bb_error_msg_and_die("packet size must be 0 <= s < %d.", MAXPACKET - sizeof(struct opacket)); datalen += sizeof(struct opacket); outpacket = (struct opacket *)xmalloc((unsigned)datalen); memset(outpacket, 0, datalen); outpacket->ip.ip_dst = to->sin_addr; outpacket->ip.ip_tos = tos; #if defined(DMP_TRACEROUTE_1) outpacket->ip.ip_tos = (outpacket->ip.ip_tos)<<2; #endif outpacket->ip.ip_v = IPVERSION; outpacket->ip.ip_id = 0; ident = (getpid() & 0xffff) | 0x8000; if ((sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) bb_perror_msg_and_die(bb_msg_can_not_create_raw_socket); s = create_icmp_socket(); #ifdef CONFIG_FEATURE_TRACEROUTE_SO_DEBUG if (options & SO_DEBUG) (void) setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof(on)); #endif if (options & SO_DONTROUTE) (void) setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&on, sizeof(on)); #ifdef SO_SNDBUF if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&datalen, sizeof(datalen)) < 0) bb_perror_msg_and_die("SO_SNDBUF"); #endif #ifdef IP_HDRINCL if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, (char *)&on, sizeof(on)) < 0) bb_perror_msg_and_die("IP_HDRINCL"); #endif #ifdef CONFIG_FEATURE_TRACEROUTE_SO_DEBUG if (options & SO_DEBUG) (void) setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof(on)); #endif if (options & SO_DONTROUTE) (void) setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, (char *)&on, sizeof(on)); if (source) { memset(&from, 0, sizeof(struct sockaddr)); from.sin_family = AF_INET; from.sin_addr.s_addr = inet_addr(source); if (from.sin_addr.s_addr == -1) bb_error_msg_and_die("unknown host %s", source); outpacket->ip.ip_src = from.sin_addr; #ifndef IP_HDRINCL if (bind(sndsock, (struct sockaddr *)&from, sizeof(from)) < 0) bb_perror_msg_and_die("bind"); #endif } fprintf(stderr, "traceroute to %s (%s)", hostname, inet_ntoa(to->sin_addr)); if (source) fprintf(stderr, " from %s", source); fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, datalen); for (ttl = 1; ttl <= max_ttl; ++ttl) { u_long lastaddr = 0; int got_there = 0; int unreachable = 0; #if defined(DMP_TRACEROUTE_1) pTraceRouteInfo->routeHopsNumberOfEntries++; #endif printf("%2d ", ttl); for (probe = 0; probe < nprobes; ++probe) { int cc, reset_timer; struct timeval t1, t2; struct timezone tz; struct ip *ip; (void) gettimeofday(&t1, &tz); send_probe(++seq, ttl); reset_timer = 1; while ((cc = wait_for_reply(s, &from, reset_timer)) != 0) { (void) gettimeofday(&t2, &tz); if ((i = packet_ok(packet, cc, &from, seq))) { reset_timer = 1; if (from.sin_addr.s_addr != lastaddr) { print(packet, cc, &from); lastaddr = from.sin_addr.s_addr; } printf(" %g ms", deltaT(&t1, &t2)); #if defined(DMP_TRACEROUTE_1) struct icmp *hopIcp; int hopHlen; struct ip *hopIp; hopIp = (struct ip *) packet; hopHlen = hopIp->ip_hl << 2; hopIcp = (struct icmp *)(packet + hopHlen); repTime = ((int)(t2.tv_sec - t1.tv_sec) * 1000 + (int)(t2.tv_usec - t1.tv_usec) / 1000); sprintf(strRepTime, "%d,", repTime); pTraceRouteInfo->responseTime+=repTime; pTraceRouteInfo->routeHops[ttl-1].hopErrorCode = hopIcp->icmp_code; sprintf(pTraceRouteInfo->routeHops[ttl-1].hopHost, "%s", inet_ntoa(from.sin_addr)); sprintf(pTraceRouteInfo->routeHops[ttl-1].hopHostAddress, "%s", inet_ntoa(from.sin_addr)); strcat(pTraceRouteInfo->routeHops[ttl-1].hopRTTimes, strRepTime); #endif switch(i - 1) { case ICMP_UNREACH_PORT: ip = (struct ip *)packet; if (ip->ip_ttl <= 1) printf(" !"); ++got_there; break; case ICMP_UNREACH_NET: ++unreachable; printf(" !N"); break; case ICMP_UNREACH_HOST: ++unreachable; printf(" !H"); break; case ICMP_UNREACH_PROTOCOL: ++got_there; printf(" !P"); break; case ICMP_UNREACH_NEEDFRAG: ++unreachable; printf(" !F"); break; case ICMP_UNREACH_SRCFAIL: ++unreachable; printf(" !S"); break; } break; } else reset_timer = 0; } if (cc == 0) { #if defined(AEI_VDSL_CUSTOMER_NCS) failcount++; #endif printf(" *"); } #if defined(AEI_VDSL_CUSTOMER_NCS) else failcount=0; #endif (void) fflush(stdout); } putchar('\n'); if (got_there || (unreachable && unreachable >= nprobes-1)) { #if defined(DMP_TRACEROUTE_1) if (got_there) { AEI_sendTraceRouteEventMessage(pTraceRouteInfo, Complete); } else if (unreachable && unreachable >= nprobes-1) { AEI_sendTraceRouteEventMessage(pTraceRouteInfo, Error_MaxHopCountExceeded); } #endif return 0; } #if defined(AEI_VDSL_CUSTOMER_NCS) #if defined(AEI_VDSL_CUSTOMER_QWEST_Q2000) if (failcount >= nprobes*2&&ttl_set_flag==0) #else if (failcount >= nprobes*2) #endif { #if defined(DMP_TRACEROUTE_1) AEI_sendTraceRouteEventMessage(pTraceRouteInfo, Error_MaxHopCountExceeded); #endif return 0; } #endif } #if defined(DMP_TRACEROUTE_1) AEI_sendTraceRouteEventMessage(pTraceRouteInfo, Error_MaxHopCountExceeded); #endif return 0; }
static int send_probe(int ifindex, __u32 addr) { struct ifreq ifr = { .ifr_ifindex = ifindex }; struct sockaddr_in dst = { .sin_family = AF_INET, .sin_port = htons(1025), .sin_addr.s_addr = addr, }; socklen_t len; unsigned char buf[256]; struct arphdr *ah = (struct arphdr *)buf; unsigned char *p = (unsigned char *)(ah+1); struct sockaddr_ll sll = { .sll_family = AF_PACKET, .sll_ifindex = ifindex, .sll_protocol = htons(ETH_P_ARP), }; if (ioctl(udp_sock, SIOCGIFNAME, &ifr)) return -1; if (ioctl(udp_sock, SIOCGIFHWADDR, &ifr)) return -1; if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) return -1; if (setsockopt(udp_sock, SOL_SOCKET, SO_BINDTODEVICE, ifr.ifr_name, strlen(ifr.ifr_name)+1) < 0) return -1; if (connect(udp_sock, (struct sockaddr *)&dst, sizeof(dst)) < 0) return -1; len = sizeof(dst); if (getsockname(udp_sock, (struct sockaddr *)&dst, &len) < 0) return -1; ah->ar_hrd = htons(ifr.ifr_hwaddr.sa_family); ah->ar_pro = htons(ETH_P_IP); ah->ar_hln = 6; ah->ar_pln = 4; ah->ar_op = htons(ARPOP_REQUEST); memcpy(p, ifr.ifr_hwaddr.sa_data, ah->ar_hln); p += ah->ar_hln; memcpy(p, &dst.sin_addr, 4); p += 4; memset(sll.sll_addr, 0xFF, sizeof(sll.sll_addr)); memcpy(p, &sll.sll_addr, ah->ar_hln); p += ah->ar_hln; memcpy(p, &addr, 4); p += 4; if (sendto(pset[0].fd, buf, p-buf, 0, (struct sockaddr *)&sll, sizeof(sll)) < 0) return -1; stats.probes_sent++; return 0; } /* Be very tough on sending probes: 1 per second with burst of 3. */ static int queue_active_probe(int ifindex, __u32 addr) { static struct timeval prev; static int buckets; struct timeval now; gettimeofday(&now, NULL); if (prev.tv_sec) { int diff = (now.tv_sec-prev.tv_sec)*1000+(now.tv_usec-prev.tv_usec)/1000; buckets += diff; } else { buckets = broadcast_burst; } if (buckets > broadcast_burst) buckets = broadcast_burst; if (buckets >= broadcast_rate && !send_probe(ifindex, addr)) { buckets -= broadcast_rate; prev = now; return 0; } stats.probes_suppressed++; return -1; } static int respond_to_kernel(int ifindex, __u32 addr, char *lla, int llalen) { struct { struct nlmsghdr n; struct ndmsg ndm; char buf[256]; } req = { .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)), .n.nlmsg_flags = NLM_F_REQUEST, .n.nlmsg_type = RTM_NEWNEIGH, .ndm.ndm_family = AF_INET, .ndm.ndm_state = NUD_STALE, .ndm.ndm_ifindex = ifindex, .ndm.ndm_type = RTN_UNICAST, }; addattr_l(&req.n, sizeof(req), NDA_DST, &addr, 4); addattr_l(&req.n, sizeof(req), NDA_LLADDR, lla, llalen); return rtnl_send(&rth, &req, req.n.nlmsg_len) <= 0; } static void prepare_neg_entry(__u8 *ndata, __u32 stamp) { ndata[0] = 0xFF; ndata[1] = 0; ndata[2] = stamp>>24; ndata[3] = stamp>>16; ndata[4] = stamp>>8; ndata[5] = stamp; } static int do_one_request(struct nlmsghdr *n) { struct ndmsg *ndm = NLMSG_DATA(n); int len = n->nlmsg_len; struct rtattr *tb[NDA_MAX+1]; struct dbkey key; DBT dbkey, dbdat; int do_acct = 0; if (n->nlmsg_type == NLMSG_DONE) { dbase->sync(dbase, 0); /* Now we have at least mirror of kernel db, so that * may start real resolution. */ do_sysctl_adjustments(); return 0; } if (n->nlmsg_type != RTM_GETNEIGH && n->nlmsg_type != RTM_NEWNEIGH) return 0; len -= NLMSG_LENGTH(sizeof(*ndm)); if (len < 0) return -1; if (ndm->ndm_family != AF_INET || (ifnum && !handle_if(ndm->ndm_ifindex)) || ndm->ndm_flags || ndm->ndm_type != RTN_UNICAST || !(ndm->ndm_state&~NUD_NOARP)) return 0; parse_rtattr(tb, NDA_MAX, NDA_RTA(ndm), len); if (!tb[NDA_DST]) return 0; key.iface = ndm->ndm_ifindex; memcpy(&key.addr, RTA_DATA(tb[NDA_DST]), 4); dbkey.data = &key; dbkey.size = sizeof(key); if (dbase->get(dbase, &dbkey, &dbdat, 0) != 0) { dbdat.data = 0; dbdat.size = 0; } if (n->nlmsg_type == RTM_GETNEIGH) { if (!(n->nlmsg_flags&NLM_F_REQUEST)) return 0; if (!(ndm->ndm_state&(NUD_PROBE|NUD_INCOMPLETE))) { stats.app_bad++; return 0; } if (ndm->ndm_state&NUD_PROBE) { /* If we get this, kernel still has some valid * address, but unicast probing failed and host * is either dead or changed its mac address. * Kernel is going to initiate broadcast resolution. * OK, we invalidate our information as well. */ if (dbdat.data && !IS_NEG(dbdat.data)) stats.app_neg++; dbase->del(dbase, &dbkey, 0); } else { /* If we get this kernel does not have any information. * If we have something tell this to kernel. */ stats.app_recv++; if (dbdat.data && !IS_NEG(dbdat.data)) { stats.app_success++; respond_to_kernel(key.iface, key.addr, dbdat.data, dbdat.size); return 0; } /* Sheeit! We have nothing to tell. */ /* If we have recent negative entry, be silent. */ if (dbdat.data && NEG_VALID(dbdat.data)) { if (NEG_CNT(dbdat.data) >= active_probing) { stats.app_suppressed++; return 0; } do_acct = 1; } } if (active_probing && queue_active_probe(ndm->ndm_ifindex, key.addr) == 0 && do_acct) { NEG_CNT(dbdat.data)++; dbase->put(dbase, &dbkey, &dbdat, 0); } } else if (n->nlmsg_type == RTM_NEWNEIGH) { if (n->nlmsg_flags&NLM_F_REQUEST) return 0; if (ndm->ndm_state&NUD_FAILED) { /* Kernel was not able to resolve. Host is dead. * Create negative entry if it is not present * or renew it if it is too old. */ if (!dbdat.data || !IS_NEG(dbdat.data) || !NEG_VALID(dbdat.data)) { __u8 ndata[6]; stats.kern_neg++; prepare_neg_entry(ndata, time(NULL)); dbdat.data = ndata; dbdat.size = sizeof(ndata); dbase->put(dbase, &dbkey, &dbdat, 0); } } else if (tb[NDA_LLADDR]) { if (dbdat.data && !IS_NEG(dbdat.data)) { if (memcmp(RTA_DATA(tb[NDA_LLADDR]), dbdat.data, dbdat.size) == 0) return 0; stats.kern_change++; } else { stats.kern_new++; } dbdat.data = RTA_DATA(tb[NDA_LLADDR]); dbdat.size = RTA_PAYLOAD(tb[NDA_LLADDR]); dbase->put(dbase, &dbkey, &dbdat, 0); } } return 0; } static void load_initial_table(void) { if (rtnl_wilddump_request(&rth, AF_INET, RTM_GETNEIGH) < 0) { perror("dump request failed"); exit(1); } } static void get_kern_msg(void) { int status; struct nlmsghdr *h; struct sockaddr_nl nladdr = {}; struct iovec iov; char buf[8192]; struct msghdr msg = { (void *)&nladdr, sizeof(nladdr), &iov, 1, NULL, 0, 0 }; iov.iov_base = buf; iov.iov_len = sizeof(buf); status = recvmsg(rth.fd, &msg, MSG_DONTWAIT); if (status <= 0) return; if (msg.msg_namelen != sizeof(nladdr)) return; if (nladdr.nl_pid) return; for (h = (struct nlmsghdr *)buf; status >= sizeof(*h); ) { int len = h->nlmsg_len; int l = len - sizeof(*h); if (l < 0 || len > status) return; if (do_one_request(h) < 0) return; status -= NLMSG_ALIGN(len); h = (struct nlmsghdr *)((char *)h + NLMSG_ALIGN(len)); } }