void send6(pcs *pc, struct packet *m) { ethdr *eh = (ethdr *)(m->data); ip6hdr *ip; if (eh->type != htons(ETHERTYPE_IPV6)) { del_pkt(m); return; } fix_dmac6(pc, m); ip = (ip6hdr *)(eh + 1); m = ipfrag6(m, findmtu6(pc, &ip->dst)); enq(&pc->oq, m); }
void send4(pcs *pc, struct packet *m) { ethdr *eh = (ethdr *)(m->data); if (eh->type == htons(ETHERTYPE_IPV6)) { send6(pc, m); return; } if (eh->type != htons(ETHERTYPE_IP)) { del_pkt(m); return; } fix_dmac(pc, m); if (pc->ip4.flags & IPF_FRAG) { m = ipfrag(m, pc->mtu); } enq(&pc->oq, m); }
/* ping host , char *cmdstr*/ int run_ping6(int argc, char **argv) { pcs *pc = &vpc[pcid]; struct in6_addr ipaddr; struct packet *m = NULL; int i; char *p; char proto_seq[16]; int count = 5; printf("\n"); i = 2; for (i = 2; i < argc; i++) { if (!strcmp(argv[i], "-c")) { if ((i + 1) < argc && digitstring(argv[i + 1])) count = atoi(argv[i + 1]); break; } } if (vinet_pton6(AF_INET6, argv[1], &ipaddr) != 1) { printf("Invalid address: %s\n", argv[1]); return 0; } memcpy(pc->mscb.dip6.addr8, ipaddr.s6_addr, 16); if (pc->mscb.dip6.addr16[0] != IPV6_ADDR_INT16_ULL) memcpy(pc->mscb.sip6.addr8, pc->ip6.ip.addr8, 16); else memcpy(pc->mscb.sip6.addr8, pc->link6.ip.addr8, 16); /* ping self, discard options */ if (IP6EQ(&pc->mscb.sip6, &pc->mscb.dip6)) { i = 1; while (i < 6) { printf("%s icmp_seq=%d ttl=%d time=0.001 ms\n", argv[1], i++, pc->mscb.ttl); delay_ms(1); } return 1; } /* find destination */ p = (char*)nbDiscovery(pc, &pc->mscb.dip6); if (p == NULL) { printf("host (%s) not reachable\n", argv[1]); return 0; } memcpy(pc->mscb.dmac, p, 6); if (pc->mscb.proto == IPPROTO_ICMP) { pc->mscb.proto = IPPROTO_ICMPV6; strcpy(proto_seq, "icmp6_seq"); } else if (pc->mscb.proto == IPPROTO_TCP) { strcpy(proto_seq, "tcp6_seq"); } else if (pc->mscb.proto == IPPROTO_UDP) { strcpy(proto_seq, "udp6_seq"); } if (pc->mscb.proto == IPPROTO_TCP && pc->mscb.flags == 0) { i = 0; while ((i++ < count || count == -1) && !ctrl_c) { struct timeval ts0, ts; u_int usec; int k; int dsize = pc->mscb.dsize; int traveltime = 1; if (i > 1) delay_ms(pc->mscb.waittime); /* clear the input queue */ while ((m = deq(&pc->iq)) != NULL); /* connect the remote */ gettimeofday(&(ts), (void*)0); k = tcp_open(IPV6_VERSION); /* restore data size */ pc->mscb.dsize = dsize; gettimeofday(&(ts0), (void*)0); usec = (ts0.tv_sec - ts.tv_sec) * 1000000 + ts0.tv_usec - ts.tv_usec; if (k == 0) { printf("Connect %d@%s timeout\n", pc->mscb.dport, argv[1]); continue; } else if (k == 2) { char buf[INET6_ADDRSTRLEN + 1]; memset(buf, 0, sizeof(buf)); vinet_ntop6(AF_INET6, &pc->mscb.rdip6, buf, INET6_ADDRSTRLEN + 1); printf("*%s %s=%d ttl=%d time=%.3f ms", buf, proto_seq, i++, pc->mscb.rttl, usec / 1000.0); printf(" (ICMP type:%d, code:%d, %s)\n", pc->mscb.icmptype, pc->mscb.icmpcode, icmpTypeCode2String(6, pc->mscb.icmptype, pc->mscb.icmpcode)); continue; } else if (k == 3) { printf("Connect %d@%s RST returned\n", pc->mscb.dport, argv[1]); continue; } printf("Connect %d@%s seq=%d ttl=%d time=%.3f ms\n", pc->mscb.dport, argv[1], i, pc->mscb.rttl, usec / 1000.0); traveltime = 0.6 * usec / 1000; /* send data */ delay_ms(traveltime); gettimeofday(&(ts), (void*)0); k = tcp_send(IPV6_VERSION); if (k == 0) { printf("SendData %d@%s timeout\n", pc->mscb.dport, argv[1]); continue; } gettimeofday(&(ts0), (void*)0); usec = (ts0.tv_sec - ts.tv_sec) * 1000000 + ts0.tv_usec - ts.tv_usec; printf("SendData %d@%s seq=%d ttl=%d time=%.3f ms\n", pc->mscb.dport, argv[1], i, pc->mscb.rttl, usec / 1000.0); /* close */ if (k != 2) delay_ms(traveltime); gettimeofday(&(ts), (void*)0); k = tcp_close(IPV6_VERSION); if (k == 0) { printf("Close %d@%s timeout\n", pc->mscb.dport, argv[1]); continue; } gettimeofday(&(ts0), (void*)0); usec = (ts0.tv_sec - ts.tv_sec) * 1000000 + ts0.tv_usec - ts.tv_usec; printf("Close %d@%s seq=%d ttl=%d time=%.3f ms\n", pc->mscb.dport, argv[1], i, pc->mscb.rttl, usec / 1000.0); } } else { i = 1; while ((i <= count || count == -1) && !ctrl_c) { struct packet *p; struct timeval tv; u_int usec; int respok = 0; pc->mscb.sn = i; pc->mscb.timeout = time_tick; m = packet6(&pc->mscb); if (m == NULL) { printf("out of memory\n"); return false; } gettimeofday(&(tv), (void*)0); enq(&pc->oq, m); while (!timeout(tv, pc->mscb.waittime) && !ctrl_c) { delay_ms(1); respok = 0; while ((p = deq(&pc->iq)) != NULL && !respok && !timeout(tv, pc->mscb.waittime) && !ctrl_c) { pc->mscb.icmptype = pc->mscb.icmpcode = 0; respok = response6(p, &pc->mscb); usec = (p->ts.tv_sec - tv.tv_sec) * 1000000 + p->ts.tv_usec - tv.tv_usec; del_pkt(p); if (respok == 0) continue; tv.tv_sec = 0; if ((pc->mscb.proto == IPPROTO_ICMPV6 && pc->mscb.icmptype == ICMP6_ECHO_REPLY) || (pc->mscb.proto == IPPROTO_UDP && respok == IPPROTO_UDP)|| (pc->mscb.proto == IPPROTO_TCP && respok == IPPROTO_TCP)) { printf("%s %s=%d ttl=%d time=%.3f ms\n", argv[1], proto_seq, i++, pc->mscb.rttl, usec / 1000.0); break; } if (respok == IPPROTO_ICMPV6) { char buf[INET6_ADDRSTRLEN + 1]; memset(buf, 0, sizeof(buf)); vinet_ntop6(AF_INET6, &pc->mscb.rdip6, buf, INET6_ADDRSTRLEN + 1); printf("*%s %s=%d ttl=%d time=%.3f ms", buf, proto_seq, i++, pc->mscb.rttl, usec / 1000.0); printf(" (ICMP type:%d, code:%d, %s)\n", pc->mscb.icmptype, pc->mscb.icmpcode, icmpTypeCode2String(6, pc->mscb.icmptype, pc->mscb.icmpcode)); break; } } } if (!respok && !ctrl_c) printf("%s %s=%d timeout\n", argv[1], proto_seq, i++); } } return 1; }
int run_tracert6(int argc, char **argv) { int i, j; struct packet *m; pcs *pc = &vpc[pcid]; u_char *dmac; int ok = 0; struct in6_addr ipaddr; ip6 ip; int pktnum = 3; int count = 99; printf("\n"); if (argc < 2) { printf("incompleted command.\n"); return 0; } i = 2; for (i = 2; i < argc; i++) { if (!strcmp(argv[i], "-c")) { if ((i + 1) < argc && digitstring(argv[i + 1])) count = atoi(argv[i + 1]); break; } } if (count == 99 && digitstring(argv[argc - 1])) count = atoi(argv[argc - 1]); if (optind < argc && digitstring(argv[optind])) count = atoi(argv[optind]); if (count < 1 || count > 64) count = 64; if (vinet_pton6(AF_INET6, argv[1], &ipaddr) != 1) { printf("Invalid address: %s\n", argv[1]); return 0; } memcpy(pc->mscb.dip6.addr8, ipaddr.s6_addr, 16); if (pc->mscb.dip6.addr16[0] != IPV6_ADDR_INT16_ULL) memcpy(pc->mscb.sip6.addr8, pc->ip6.ip.addr8, 16); else memcpy(pc->mscb.sip6.addr8, pc->link6.ip.addr8, 16); dmac = nbDiscovery(pc, &ip); if (dmac == NULL) { printf("host (%s) not reachable\n", argv[1]); return 0; } memcpy(pc->mscb.dmac, dmac, 6); printf("trace to %s, %d hops max\n", argv[1], count); /* send the udp packets */ i = 1; while (i <= count && !ctrl_c) { struct packet *p; struct timeval tv; u_int usec; int k; printf("%2d ", i); for (j = 0; j < pktnum && !ctrl_c; j++) { pc->mscb.ttl = i; m = packet6(&pc->mscb); if (m == NULL) { printf("out of memory\n"); return 0; } gettimeofday(&(tv), (void*)0); enq(&pc->oq, m); k = 0; while (!timeout(tv, pc->mscb.waittime) && !ctrl_c) { delay_ms(1); ok = 0; while ((p = deq(&pc->iq)) != NULL && !ok && !timeout(tv, pc->mscb.waittime) && !ctrl_c) { ok = response6(p, &pc->mscb); usec = (p->ts.tv_sec - tv.tv_sec) * 1000000 + p->ts.tv_usec - tv.tv_usec; del_pkt(p); if (pc->mscb.icmptype == ICMP6_TIME_EXCEEDED || IP6EQ(&(pc->mscb.dip6), &(pc->mscb.rdip6))) { if (j == 0) { char buf[128]; memcpy(ipaddr.s6_addr, pc->mscb.rdip6.addr8, 16); memset(buf, 0, 128); vinet_ntop6(AF_INET6, &ipaddr, buf, INET6_ADDRSTRLEN + 1); printf("%s ", buf); } printf(" %.3f ms", usec / 1000.0);fflush(stdout); tv.tv_sec = 0; break; } else if (pc->mscb.icmptype == ICMP6_DST_UNREACH || pc->mscb.icmptype == ICMP6_DST_UNREACH_NOPORT) { if (j == 0) { char buf[128]; memcpy(ipaddr.s6_addr, pc->mscb.rdip6.addr8, 16); memset(buf, 0, 128); vinet_ntop6(AF_INET6, &ipaddr, buf, INET6_ADDRSTRLEN + 1); printf("*%s %.3f ms (ICMP type:%d, code:%d, %s)\n", buf, usec / 1000.0, pc->mscb.icmptype, pc->mscb.icmpcode, icmpTypeCode2String(6, pc->mscb.icmptype, pc->mscb.icmpcode)); } tv.tv_sec = 0; return 1; } } k++; } if (!ok && !ctrl_c) printf(" *"); } printf("\n"); i++; if (pc->mscb.icmptype == ICMP6_DST_UNREACH) break; } return 1; }