/* * Construct an IGMP message in the output packet buffer. The caller may * have already placed data in that buffer, of length 'datalen'. */ size_t build_igmp(u_int32 src, u_int32 dst, int type, int code, u_int32 group, int datalen) { struct ip *ip; struct igmp *igmp; extern int curttl; size_t len = MIN_IP_HEADER_LEN + IGMP_MINLEN + datalen; ip = (struct ip *)send_buf; ip->ip_src.s_addr = src; ip->ip_dst.s_addr = dst; ip->ip_len = htons(len); if (IN_MULTICAST(ntohl(dst))) { ip->ip_ttl = curttl; } else { ip->ip_ttl = MAXTTL; } igmp = (struct igmp *)(send_buf + MIN_IP_HEADER_LEN); igmp->igmp_type = type; igmp->igmp_code = code; igmp->igmp_group.s_addr = group; igmp->igmp_cksum = 0; igmp->igmp_cksum = inet_cksum((u_int16_t *)igmp, IGMP_MINLEN + datalen); return len; }
errno_t mbuf_inet_cksum(mbuf_t mbuf, int protocol, u_int32_t offset, u_int32_t length, u_int16_t *csum) { if (mbuf == NULL || length == 0 || csum == NULL || (u_int32_t)mbuf->m_pkthdr.len < (offset + length)) return (EINVAL); *csum = inet_cksum(mbuf, protocol, offset, length); return (0); }
int pimdm_output(char *buf,u_int32 src,u_int32 dst,int type,int length) {//提供缓存,源、目的、类型和长度,发送PIM报文 struct sockaddr_in sockdst; struct ip *ip; struct pim *pim; int sendlen; int setloop=0; ip=(struct ip*)buf; ip->ip_v=4; ip->ip_hl=(sizeof(struct ip)>>2); ip->ip_tos=0; ip->ip_id=0; ip->ip_off=0; ip->ip_p=IPPROTO_PIM; ip->ip_sum=0; ip->ip_len=sizeof(struct ip)+sizeof(struct pim)+length; ip->ip_src.s_addr=src; ip->ip_dst.s_addr=dst; ip->ip_ttl=1; sendlen=ip->ip_len; pim=(struct pim *)(buf+sizeof(struct ip)); pim->pim_type=type; pim->pim_vers=2; pim->pim_cksum=0; pim->pim_cksum=inet_cksum((u_int16 *)pim,sizeof(struct pim)+length); if(IN_MULTICAST(ntohl(dst))) { k_set_if(pimsocket,src); setloop=1; k_set_loop(pimsocket,1); } bzero((void *)&sockdst,sizeof(sockdst)); sockdst.sin_family=AF_INET; sockdst.sin_len=sizeof(sockdst); sockdst.sin_addr.s_addr=dst; if (sendto(pimsocket,pim_send_buf,sendlen,0,(struct sockaddr *)&sockdst,sizeof(sockdst))<0) { if (setloop) k_set_loop(pimsocket,0); return 0; } if (setloop) k_set_loop(pimsocket,0); return 1; }
static void ping4(len_and_sockaddr *lsa) { struct icmp *pkt; int c; pkt = (struct icmp *) G.packet; /*memset(pkt, 0, sizeof(G.packet)); already is */ pkt->icmp_type = ICMP_ECHO; pkt->icmp_id = G.myid; pkt->icmp_cksum = inet_cksum((uint16_t *) pkt, sizeof(G.packet)); xsendto(pingsock, G.packet, DEFDATALEN + ICMP_MINLEN, &lsa->u.sa, lsa->len); /* listen for replies */ while (1) { #if 0 struct sockaddr_in from; socklen_t fromlen = sizeof(from); c = recvfrom(pingsock, G.packet, sizeof(G.packet), 0, (struct sockaddr *) &from, &fromlen); #else c = recv(pingsock, G.packet, sizeof(G.packet), 0); #endif if (c < 0) { if (errno != EINTR) bb_perror_msg("recvfrom"); continue; } if (c >= 76) { /* ip + icmp */ struct iphdr *iphdr = (struct iphdr *) G.packet; pkt = (struct icmp *) (G.packet + (iphdr->ihl << 2)); /* skip ip hdr */ if (pkt->icmp_id != G.myid) continue; /* not our ping */ if (pkt->icmp_type == ICMP_ECHOREPLY) break; } } if (ENABLE_FEATURE_CLEAN_UP) close(pingsock); }
int valid_packet(u_int32 src,char *packet,int length) {//检验包的校验和 源地址 接口等信息,确定该包是否有效,有效返回1,否则返回0 vifi_t vif; struct myvif *myv; if(inet_cksum((u_int16 *)packet,length)) { log(LOG_INFO,0,"Checking sum error!"); return 0; } vif=find_vif_direct(src); if(vif==0) { //log(LOG_INFO,"Source address error!Don't handle!"); return 0; } myv=&myvifs[vif]; if(myv->is_active==0) { log(LOG_INFO,"Interface is not active!"); return 0; } return 1; }
u_int16_t inet_cksum_simple(struct mbuf *m, int len) { return (inet_cksum(m, 0, 0, len)); }
int main(int argc, char** argv) { pcap_dumper_t *dumper; pcap_t *p; struct pcap_pkthdr header; u_char *packet; int i; struct sockaddr *sin_src; struct sockaddr *sin_net; struct sockaddr *sin_dst; struct sockaddr *sin_mask; int sendsize; struct options_args opts; FILE* fp_domain; char * domain; int q_class; int q_type; /** * * headers */ struct ether_header *eth; struct iphdr *ip; struct ip6_hdr *ip6; struct udphdr *udp; u_char *dns; setoptions(argc, argv, &opts); header.ts.tv_sec = 0; header.ts.tv_usec = 0; packet = calloc(sizeof (u_char) * 4096, 1); sin_src = calloc(sizeof (struct sockaddr_storage), 1); sin_net = calloc(sizeof (struct sockaddr_storage), 1); sin_dst = calloc(sizeof (struct sockaddr_storage), 1); sin_mask = calloc(sizeof (struct sockaddr_storage), 1); domain = calloc(sizeof (char) * 1024, 1); if(packet == NULL || sin_src == NULL || sin_net == NULL || sin_dst == NULL || sin_mask == NULL || domain == NULL) { return -1; } /** * * ETHERNET static */ eth = (struct ether_header *) packet; if (ether_setaddr(opts.smac, &(eth->ether_shost)) < 0) { fprintf(stderr, "smac error\n"); return 1; } if (ether_setaddr(opts.dmac, &(eth->ether_dhost)) < 0) { fprintf(stderr, "dmac error\n"); return 1; } /** * * IP static */ if (getipaddr(opts.dip, sin_dst, opts.family) < 0) { fprintf(stderr, "dip error\n"); return 2; } if (getipaddr(opts.snet, sin_net, opts.family) < 0) { fprintf(stderr, "sip error\n"); return 2; } if (sin_net->sa_family != sin_dst->sa_family) { fprintf(stderr, "IP family doesn't match\n"); return 2; } set_mask(sin_mask, sin_net->sa_family, opts.smask); if (sin_net->sa_family == AF_INET) { eth->ether_type = htons(ETHERTYPE_IP); ip = (struct iphdr *) (packet + ETHER_HDR_LEN); ip->daddr = ((struct sockaddr_in *) sin_dst)->sin_addr.s_addr; ip->version = 4; ip->ihl = 5; // no opts ip->frag_off = 0; ip->id = 0; ip->protocol = IPPROTO_UDP; ip->tos = 0; ip->ttl = IPDEFTTL; udp = (struct udphdr *) (((void *) ip) + IP_HDR_LEN); } else if (sin_net->sa_family == AF_INET6) { eth->ether_type = htons(ETHERTYPE_IPV6); ip6 = (struct ip6_hdr *) (packet + ETHER_HDR_LEN); ip6->ip6_vfc = 6 << 4; ip6->ip6_hlim = IPDEFTTL; ip6->ip6_nxt = IPPROTO_UDP; memcpy(&(ip6->ip6_dst), &(((struct sockaddr_in6 *) sin_dst)->sin6_addr), 16); udp = (struct udphdr *) (((void *) ip6) + IP6_HDR_LEN); } else { fprintf(stderr, "Family unknown\n"); return 2; } /** * * UDP static */ udp->check = 0; udp->dest = htons(53); /** * * DNS static */ dns = (u_char *) (((void *) udp) + UDP_HDR_LEN); p = pcap_open_dead(DLT_EN10MB, PCAP_SNAPLEN); dumper = pcap_dump_open(p, opts.out_file_name); if(dumper == NULL) { fprintf(stderr, "Can't open output file\n"); pcap_close(p); return 3; } init_domain_file(&fp_domain, opts.in_file_name); if (fp_domain == NULL) { fprintf(stderr, "Can't open queries file\n"); pcap_dump_close(dumper); pcap_close(p); return 4; } for (i = 0; i < opts.count; i++) { /** * * DNS dynamic */ nextdomain(fp_domain, &domain, &q_type, &q_class); sendsize = res_mkquery(QUERY, domain, q_class, q_type, NULL, 0, NULL, dns, PACKETSZ); /** * * UDP dynamic */ udp->source = htons(rand()); udp->len = htons(sendsize + UDP_HDR_LEN); /** * * IP dynamic */ get_rand_addr(sin_net, sin_mask, sin_src); if (sin_net->sa_family == AF_INET) { ip->saddr = ((struct sockaddr_in *) sin_src)->sin_addr.s_addr; ip->tot_len = htons(sendsize + UDP_HDR_LEN + (ip->ihl * 4)); header.len = sendsize + UDP_HDR_LEN + (ip->ihl * 4) + ETHER_HDR_LEN; ip->check = 0; ip->check = inet_cksum(ip, (ip->ihl * 4)); } else if (sin_net->sa_family == AF_INET6) { memcpy(&(ip6->ip6_src), &(((struct sockaddr_in6 *) sin_src)->sin6_addr), 16); ip6->ip6_plen = htons(sendsize + UDP_HDR_LEN); header.len = sendsize + UDP_HDR_LEN + sizeof (struct ip6_hdr) +ETHER_HDR_LEN; } header.caplen = header.len; if (header.len > opts.mtu) { fprintf(stderr, "too long: %s needs %d MTU is %d\n", domain,header.len, opts.mtu); } else { pcap_dump(dumper, &header, packet); } } pcap_dump_close(dumper); pcap_close(p); fclose(fp_domain); return (EXIT_SUCCESS); }
static void send_probe(int seq, int ttl) { int len, res; void *out; /* Payload */ #if ENABLE_TRACEROUTE6 if (dest_lsa->u.sa.sa_family == AF_INET6) { struct outdata6_t *pkt = (struct outdata6_t *) outip; pkt->ident6 = htonl(ident); pkt->seq6 = htonl(seq); /*gettimeofday(&pkt->tv, &tz);*/ } else #endif { outdata->seq = seq; outdata->ttl = ttl; // UNUSED: was storing gettimeofday's result there, but never ever checked it /*memcpy(&outdata->tv, tp, sizeof(outdata->tv));*/ if (option_mask32 & OPT_USE_ICMP) { outicmp->icmp_seq = htons(seq); /* Always calculate checksum for icmp packets */ outicmp->icmp_cksum = 0; outicmp->icmp_cksum = inet_cksum((uint16_t *)outicmp, packlen - (sizeof(*outip) + optlen)); if (outicmp->icmp_cksum == 0) outicmp->icmp_cksum = 0xffff; } } //BUG! verbose is (x & OPT_VERBOSE), not a counter! #if 0 //ENABLE_FEATURE_TRACEROUTE_VERBOSE /* XXX undocumented debugging hack */ if (verbose > 1) { const uint16_t *sp; int nshorts, i; sp = (uint16_t *)outip; nshorts = (unsigned)packlen / sizeof(uint16_t); i = 0; printf("[ %d bytes", packlen); while (--nshorts >= 0) { if ((i++ % 8) == 0) printf("\n\t"); printf(" %04x", ntohs(*sp)); sp++; } if (packlen & 1) { if ((i % 8) == 0) printf("\n\t"); printf(" %02x", *(unsigned char *)sp); } printf("]\n"); } #endif #if ENABLE_TRACEROUTE6 if (dest_lsa->u.sa.sa_family == AF_INET6) { res = setsockopt(sndsock, SOL_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl)); if (res < 0) bb_perror_msg_and_die("setsockopt UNICAST_HOPS %d", ttl); out = outip; len = packlen; } else #endif { #if defined IP_TTL res = setsockopt(sndsock, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)); if (res < 0) bb_perror_msg_and_die("setsockopt ttl %d", ttl); #endif out = outicmp; len = packlen - sizeof(*outip); if (!(option_mask32 & OPT_USE_ICMP)) { out = outdata; len -= sizeof(*outudp); set_nport(&dest_lsa->u.sa, htons(port + seq)); } } res = xsendto(sndsock, out, len, &dest_lsa->u.sa, dest_lsa->len); if (res != len) bb_info_msg("sent %d octets, ret=%d", len, res); }
/* Construct a ip/udp header for a packet, send packet */ int FAST_FUNC udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt, uint32_t source_nip, int source_port, uint32_t dest_nip, int dest_port, const uint8_t *dest_arp, int ifindex) { struct sockaddr_ll dest_sll; struct ip_udp_dhcp_packet packet; unsigned padding; int fd; int result = -1; const char *msg; fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP)); if (fd < 0) { msg = "socket(%s)"; goto ret_msg; } memset(&dest_sll, 0, sizeof(dest_sll)); memset(&packet, 0, offsetof(struct ip_udp_dhcp_packet, data)); packet.data = *dhcp_pkt; /* struct copy */ dest_sll.sll_family = AF_PACKET; dest_sll.sll_protocol = htons(ETH_P_IP); dest_sll.sll_ifindex = ifindex; dest_sll.sll_halen = 6; memcpy(dest_sll.sll_addr, dest_arp, 6); if (bind(fd, (struct sockaddr *)&dest_sll, sizeof(dest_sll)) < 0) { msg = "bind(%s)"; goto ret_close; } /* We were sending full-sized DHCP packets (zero padded), * but some badly configured servers were seen dropping them. * Apparently they drop all DHCP packets >576 *ethernet* octets big, * whereas they may only drop packets >576 *IP* octets big * (which for typical Ethernet II means 590 octets: 6+6+2 + 576). * * In order to work with those buggy servers, * we truncate packets after end option byte. */ padding = DHCP_OPTIONS_BUFSIZE - 1 - udhcp_end_option(packet.data.options); packet.ip.protocol = IPPROTO_UDP; packet.ip.saddr = source_nip; packet.ip.daddr = dest_nip; packet.udp.source = htons(source_port); packet.udp.dest = htons(dest_port); /* size, excluding IP header: */ packet.udp.len = htons(UDP_DHCP_SIZE - padding); /* for UDP checksumming, ip.len is set to UDP packet len */ packet.ip.tot_len = packet.udp.len; packet.udp.check = inet_cksum((uint16_t *)&packet, IP_UDP_DHCP_SIZE - padding); /* but for sending, it is set to IP packet len */ packet.ip.tot_len = htons(IP_UDP_DHCP_SIZE - padding); packet.ip.ihl = sizeof(packet.ip) >> 2; packet.ip.version = IPVERSION; packet.ip.ttl = IPDEFTTL; packet.ip.check = inet_cksum((uint16_t *)&packet.ip, sizeof(packet.ip)); udhcp_dump_packet(dhcp_pkt); result = sendto(fd, &packet, IP_UDP_DHCP_SIZE - padding, /*flags:*/ 0, (struct sockaddr *) &dest_sll, sizeof(dest_sll)); msg = "sendto"; ret_close: close(fd); if (result < 0) { ret_msg: bb_perror_msg(msg, "PACKET"); } return result; }
int main(int argc, char** argv) { u_char *packet; int i; uint32_t ck; struct sockaddr *sin_src; struct sockaddr *sin_net; struct sockaddr *sin_dst; struct sockaddr *sin_mask; struct ip6_pseudo_hdr ps_hdr; int sendsize; struct options opts; FILE* fp_domain; char * domain; struct writer_info wi; int pkt_len; double speed_limit; double pkt_sent; int q_class; int q_type; pthread_t thread; pthread_create(&thread,NULL,readliner,&speed_limit); sleeper = 50; pkt_sent = 0; speed_limit = 50000; /** * * headers */ struct ether_header *eth; struct iphdr *ip; struct ip6_hdr *ip6; struct udphdr *udp; u_char *dns; u_char dns_opt[] = {00, 00, 0x29, 0x08, 00, 00, 00, 00, 00, 00, 00}; setoptions(argc, argv, &opts); packet = calloc(sizeof (u_char) * 4096, 1); sin_src = calloc(sizeof (struct sockaddr_storage), 1); sin_net = calloc(sizeof (struct sockaddr_storage), 1); sin_dst = calloc(sizeof (struct sockaddr_storage), 1); sin_mask = calloc(sizeof (struct sockaddr_storage), 1); domain = calloc(sizeof (char) * 1024, 1); //domain = NULL; if (packet == NULL || sin_src == NULL || sin_net == NULL || sin_dst == NULL || sin_mask == NULL || domain == NULL) { return -1; } /** * * ETHERNET static */ eth = (struct ether_header *) packet; if (ether_setaddr(opts.smac, &(eth->ether_shost)) < 0) { fprintf(stderr, "smac error:%s\n"); return 1; } if (ether_setaddr(opts.dmac, &(eth->ether_dhost)) < 0) { fprintf(stderr, "dmac error\n"); return 1; } /** * * IP static */ if (getipaddr(opts.dip, sin_dst, opts.family) < 0) { fprintf(stderr, "dip error\n"); return 2; } if (getipaddr(opts.snet, sin_net, opts.family) < 0) { fprintf(stderr, "sip error\n"); return 2; } if (sin_net->sa_family != sin_dst->sa_family) { fprintf(stderr, "IP family doesn't match\n"); return 2; } set_mask(sin_mask, sin_net->sa_family, opts.smask); if (sin_net->sa_family == AF_INET) { eth->ether_type = htons(ETHERTYPE_IP); ip = (struct iphdr *) (packet + ETHER_HDR_LEN); ip->daddr = ((struct sockaddr_in *) sin_dst)->sin_addr.s_addr; ip->version = 4; ip->ihl = 5; // no opts ip->frag_off = 0; ip->id = 0; ip->protocol = IPPROTO_UDP; ip->tos = 0; ip->ttl = IPDEFTTL; udp = (struct udphdr *) (((void *) ip) + IP_HDR_LEN); } else if (sin_net->sa_family == AF_INET6) { eth->ether_type = htons(ETHERTYPE_IPV6); ip6 = (struct ip6_hdr *) (packet + ETHER_HDR_LEN); ip6->ip6_vfc = 6 << 4; ip6->ip6_hlim = IPDEFTTL; ip6->ip6_nxt = IPPROTO_UDP; memcpy(&(ip6->ip6_dst), &(((struct sockaddr_in6 *) sin_dst)->sin6_addr), 16); udp = (struct udphdr *) (((void *) ip6) + IP6_HDR_LEN); } else { fprintf(stderr, "Family unknown\n"); return 2; } /** * * UDP static */ //udp->check = 0; udp->dest = htons(53); /** * * DNS static */ dns = (u_char *) (((void *) udp) + UDP_HDR_LEN); wopen(&wi,&opts); init_domain_file(&fp_domain, opts.in_file_name); if (fp_domain == NULL) { fprintf(stderr, "Can't open queries file\n"); wclose(&wi); return 4; } for (i = 0; i < opts.count; i++) { if(pkt_sent >= sleeper) { speed_calc(pkt_sent,speed_limit, &sleeper); pkt_sent = 0; usleep(1); } /** * * DNS dynamic */ if(nextdomain(fp_domain, &domain, &q_type, &q_class)) { printf("Can't read next domain\n"); exit(1); } sendsize = res_mkquery(QUERY, domain, q_class, q_type, NULL, 0, NULL, dns, PACKETSZ); dns[11] = 1; memcpy(dns + sendsize, dns_opt, 11); sendsize += 11; /** * * UDP dynamic */ udp->source = htons(rand()); udp->len = htons(sendsize + UDP_HDR_LEN); udp->check = 0; /** * * IP dynamic */ get_rand_addr(sin_net, sin_mask, sin_src); if (sin_net->sa_family == AF_INET) { ip->saddr = ((struct sockaddr_in *) sin_src)->sin_addr.s_addr; ip->tot_len = htons(sendsize + UDP_HDR_LEN + (ip->ihl * 4)); pkt_len = sendsize + UDP_HDR_LEN + (ip->ihl * 4) + ETHER_HDR_LEN; ip->check = 0; ip->check = inet_cksum(ip, (ip->ihl * 4), 0); } else if (sin_net->sa_family == AF_INET6) { memcpy(&(ip6->ip6_src), &(((struct sockaddr_in6 *) sin_src)->sin6_addr), 16); ip6->ip6_plen = htons(sendsize + UDP_HDR_LEN); pkt_len = sendsize + UDP_HDR_LEN + sizeof (struct ip6_hdr) +ETHER_HDR_LEN; ps_hdr.src = ip6->ip6_src; ps_hdr.dst = ip6->ip6_dst; ps_hdr.len = udp->len; ps_hdr.nh = ntohs(17); ck = inet_cksum(&ps_hdr, sizeof (ps_hdr), 0); udp->check = inet_cksum(udp, sendsize + UDP_HDR_LEN, (~ck)&0xffff); } if (pkt_len > opts.mtu) { fprintf(stderr, "too long: %s needs %d MTU is %d\n", domain, pkt_len, opts.mtu); } else { wwrite(&wi,packet,pkt_len); } pkt_sent++; } wclose(&wi); fclose(fp_domain); return (EXIT_SUCCESS); }