u_int16_t libnet_ip_check(u_int16_t *addr, int len) { int sum; sum = libnet_in_cksum(addr, len); return (LIBNET_CKSUM_CARRY(sum)); }
/***************************************************************************** * static implementations ****************************************************************************/ static uint16_t sender6_compute_icmp_payload(uint16_t icmpsum, /*{{{*/ uint16_t icmpid, uint16_t icmpseq) { int payload; struct libnet_icmpv6_hdr hdrv6; hdrv6.icmp_type = ICMP6_ECHO; hdrv6.icmp_code = 0; hdrv6.icmp_sum = htons(icmpsum); hdrv6.id = htons(icmpid); hdrv6.seq = htons(icmpseq); payload = libnet_in_cksum((uint16_t *)&hdrv6, LIBNET_ICMPV6_ECHO_H); return (uint16_t)LIBNET_CKSUM_CARRY(payload); } /*}}}*/
/*- - chksum = net.chksum(string, ...) Checksum the series of strings passed in. */ static int lnet_chksum(lua_State *L) { int interm = 0; u_int16_t chks = 0; int i; int top = lua_gettop(L); for (i = 1; i <= top; i++) { size_t length = 0; const char* src = luaL_checklstring(L, i, &length); interm += libnet_in_cksum((u_int16_t*)src, length); } chks = LIBNET_CKSUM_CARRY(interm); lua_pushlstring(L, (char *)&chks, 2); return 1; }
int update_USUM(libnet_t *l, libnet_ptag_t t) { int sum = 0; unsigned int tmp; if (tx.udp_sum != 0) return 0; sum += libnet_in_cksum((u_int16_t *) &tx.ip6_src, 16); if (tx.ip_option_s && tx.ip6_segs) sum += libnet_in_cksum((u_int16_t *) &tx.ip_option[tx.ip_option_s - 16], 16); // Use last IP address else sum += libnet_in_cksum((u_int16_t *) &tx.ip6_dst, 16); tmp = htonl(tx.udp_len); sum += libnet_in_cksum((u_int16_t *) &tmp, 4); tmp = htonl(IPPROTO_UDP); sum += libnet_in_cksum((u_int16_t *) &tmp, 4); tmp = ((htons(tx.sp) << 16) + htons(tx.dp)); sum += libnet_in_cksum((u_int16_t *) &tmp, 4); tmp = htons(tx.udp_len) << 16; sum += libnet_in_cksum((u_int16_t *) &tmp, 4); if (tx.udp_payload_s) sum += libnet_in_cksum((u_int16_t *) tx.udp_payload, tx.udp_payload_s); tx.udp_sum = ntohs(LIBNET_CKSUM_CARRY(sum)); t = libnet_build_udp(tx.sp, tx.dp, tx.udp_len, tx.udp_sum, tx.udp_payload_s ? tx.udp_payload : NULL, tx.udp_payload_s, l, t); return t; }
int update_ISUM(libnet_t *l, libnet_ptag_t t) { int sum = 0; unsigned int tmp; if (tx.icmp_chksum != 0) return 0; sum += libnet_in_cksum((u_int16_t *) &tx.ip6_src, 16); if (tx.ip_option_s && tx.ip6_segs) sum += libnet_in_cksum((u_int16_t *) &tx.ip_option[tx.ip_option_s - 16], 16); // Use last IP address else sum += libnet_in_cksum((u_int16_t *) &tx.ip6_dst, 16); tmp = htonl(LIBNET_ICMPV6_H + tx.icmp_payload_s); sum += libnet_in_cksum((u_int16_t *) &tmp, 4); tmp = htonl(IPPROTO_ICMP6); sum += libnet_in_cksum((u_int16_t *) &tmp, 4); tmp = htonl(((tx.icmp_type << 8) + tx.icmp_code)); sum += libnet_in_cksum((u_int16_t *) &tmp, 4); if (tx.icmp_payload_s) sum += libnet_in_cksum((u_int16_t *) tx.icmp_payload, tx.icmp_payload_s); tx.icmp_chksum = ntohs(LIBNET_CKSUM_CARRY(sum)); t = libnet_build_icmpv4_echo (tx.icmp_type, tx.icmp_code, tx.icmp_chksum, tx.icmp_ident, tx.icmp_sqnr, tx.icmp_payload_s ? tx.icmp_payload : NULL, tx.icmp_payload_s, l, t); return t; }
int libnet_do_checksum(libnet_t *l, u_int8_t *buf, int protocol, int len) { /* will need to update this for ipv6 at some point */ struct libnet_ipv4_hdr *iph_p; struct libnet_ipv6_hdr *ip6h_p; int is_ipv6; int ip_hl; int sum; is_ipv6 = 0; /* default to not using IPv6 */ sum = 0; iph_p = NULL; ip6h_p = NULL; if (len == 0) { snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): header length can't be zero\n", __func__); return (-1); } /* * Figure out which IP version we're dealing with. We'll assume v4 * and overlay a header structure to yank out the version. */ iph_p = (struct libnet_ipv4_hdr *)buf; if (iph_p && iph_p->ip_v == 6) { ip6h_p = (struct libnet_ipv6_hdr *)buf; is_ipv6 = 1; ip_hl = 40; } else { is_ipv6 = 0; ip_hl = iph_p->ip_hl << 2; } /* * Dug Song came up with this very cool checksuming implementation * eliminating the need for explicit psuedoheader use. Check it out. */ switch (protocol) { case IPPROTO_SCTP: { struct libnet_sctp_hdr *sctph_p = (struct libnet_sctp_hdr *)(buf + ip_hl); sctph_p->checksum = 0; sum = libnet_sctp_cksum((u_int8_t *)sctph_p, len); sctph_p->checksum = sum; break; } /* * Style note: normally I don't advocate declaring variables inside * blocks of control, but it makes good sense here. -- MDS */ case IPPROTO_TCP: { struct libnet_tcp_hdr *tcph_p = (struct libnet_tcp_hdr *)(buf + ip_hl); #if 0 #if (STUPID_SOLARIS_CHECKSUM_BUG) tcph_p->th_sum = tcph_p->th_off << 2; return (1); #endif /* STUPID_SOLARIS_CHECKSUM_BUG */ #endif #if (HAVE_HPUX11) if (l->injection_type != LIBNET_LINK) { /* * Similiar to the Solaris Checksum bug - but need to add * the size of the TCP payload (only for raw sockets). */ tcph_p->th_sum = (tcph_p->th_off << 2) + (len - (tcph_p->th_off << 2)); return (1); } #endif tcph_p->th_sum = 0; if (is_ipv6) { sum = libnet_in_cksum((u_int16_t *)&ip6h_p->ip_src, 32); } else { sum = libnet_in_cksum((u_int16_t *)&iph_p->ip_src, 8); } sum += ntohs(IPPROTO_TCP + len); sum += libnet_in_cksum((u_int16_t *)tcph_p, len); tcph_p->th_sum = LIBNET_CKSUM_CARRY(sum); break; } case IPPROTO_UDP: { struct libnet_udp_hdr *udph_p = (struct libnet_udp_hdr *)(buf + ip_hl); udph_p->uh_sum = 0; if (is_ipv6) { sum = libnet_in_cksum((u_int16_t *)&ip6h_p->ip_src, 32); } else { sum = libnet_in_cksum((u_int16_t *)&iph_p->ip_src, 8); } sum += ntohs(IPPROTO_UDP + len); sum += libnet_in_cksum((u_int16_t *)udph_p, len); udph_p->uh_sum = LIBNET_CKSUM_CARRY(sum); break; } case IPPROTO_ICMP: { struct libnet_icmpv4_hdr *icmph_p = (struct libnet_icmpv4_hdr *)(buf + ip_hl); icmph_p->icmp_sum = 0; if (is_ipv6) { sum = libnet_in_cksum((u_int16_t *)&ip6h_p->ip_src, 32); sum += ntohs(IPPROTO_ICMP6 + len); } sum += libnet_in_cksum((u_int16_t *)icmph_p, len); icmph_p->icmp_sum = LIBNET_CKSUM_CARRY(sum); break; } case IPPROTO_IGMP: { struct libnet_igmp_hdr *igmph_p = (struct libnet_igmp_hdr *)(buf + ip_hl); igmph_p->igmp_sum = 0; sum = libnet_in_cksum((u_int16_t *)igmph_p, len); igmph_p->igmp_sum = LIBNET_CKSUM_CARRY(sum); break; } case IPPROTO_RSVP: { struct libnet_rsvp_hdr *rsvph_p = (struct libnet_rsvp_hdr *)(buf + ip_hl); rsvph_p->checksum = 0; sum = libnet_in_cksum((u_int16_t *)rsvph_p, len); rsvph_p->checksum = LIBNET_CKSUM_CARRY(sum); break; } case IPPROTO_PIM: { struct libnet_pim_hdr *pim_p = (struct libnet_pim_hdr *)(buf + ip_hl); pim_p->pim_sum = 0; if ((pim_p->pim_ver_type & 0x0f) == PIM_REGISTER) { sum = libnet_in_cksum((u_int16_t *)pim_p, LIBNET_PIM_H); } else { sum = libnet_in_cksum((u_int16_t *)pim_p, len); } pim_p->pim_sum = LIBNET_CKSUM_CARRY(sum); break; } case IPPROTO_GRE: { /* checksum is always at the same place in GRE header * in the multiple RFC version of the protocol ... ouf !!! */ struct libnet_gre_hdr *greh_p = (struct libnet_gre_hdr *)(buf + ip_hl); u_int16_t fv = ntohs(greh_p->flags_ver); if (!(fv & (GRE_CSUM|GRE_ROUTING | GRE_VERSION_0)) || !(fv & (GRE_CSUM|GRE_VERSION_1))) { snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): can't compute GRE checksum (wrong flags_ver bits: 0x%x )\n", __func__, fv); return (-1); } sum = libnet_in_cksum((u_int16_t *)greh_p, len); greh_p->gre_sum = LIBNET_CKSUM_CARRY(sum); break; } case IPPROTO_OSPF: { struct libnet_ospf_hdr *oh_p = (struct libnet_ospf_hdr *)(buf + ip_hl); oh_p->ospf_sum = 0; sum += libnet_in_cksum((u_int16_t *)oh_p, len); oh_p->ospf_sum = LIBNET_CKSUM_CARRY(sum); break; } case IPPROTO_OSPF_LSA: { struct libnet_ospf_hdr *oh_p = (struct libnet_ospf_hdr *)(buf + ip_hl); struct libnet_lsa_hdr *lsa_p = (struct libnet_lsa_hdr *)(buf + ip_hl + oh_p->ospf_len); lsa_p->lsa_sum = 0; sum += libnet_in_cksum((u_int16_t *)lsa_p, len); lsa_p->lsa_sum = LIBNET_CKSUM_CARRY(sum); break; #if 0 /* * Reworked fletcher checksum taken from RFC 1008. */ int c0, c1; struct libnet_lsa_hdr *lsa_p = (struct libnet_lsa_hdr *)buf; u_int8_t *p, *p1, *p2, *p3; c0 = 0; c1 = 0; lsa_p->lsa_cksum = 0; p = buf; p1 = buf; p3 = buf + len; /* beginning and end of buf */ while (p1 < p3) { p2 = p1 + LIBNET_MODX; if (p2 > p3) { p2 = p3; } for (p = p1; p < p2; p++) { c0 += (*p); c1 += c0; } c0 %= 255; c1 %= 255; /* modular 255 */ p1 = p2; } #if AWR_PLEASE_REWORK_THIS lsa_p->lsa_cksum[0] = (((len - 17) * c0 - c1) % 255); if (lsa_p->lsa_cksum[0] <= 0) { lsa_p->lsa_cksum[0] += 255; } lsa_p->lsa_cksum[1] = (510 - c0 - lsa_p->lsa_cksum[0]); if (lsa_p->lsa_cksum[1] > 255) { lsa_p->lsa_cksum[1] -= 255; } #endif break; #endif } case IPPROTO_IP: { iph_p->ip_sum = 0; sum = libnet_in_cksum((u_int16_t *)iph_p, ip_hl); iph_p->ip_sum = LIBNET_CKSUM_CARRY(sum); break; } case IPPROTO_VRRP: { struct libnet_vrrp_hdr *vrrph_p = (struct libnet_vrrp_hdr *)(buf + ip_hl); vrrph_p->vrrp_sum = 0; sum = libnet_in_cksum((u_int16_t *)vrrph_p, len); vrrph_p->vrrp_sum = LIBNET_CKSUM_CARRY(sum); break; } case LIBNET_PROTO_CDP: { /* XXX - Broken: how can we easily get the entire packet size? */ struct libnet_cdp_hdr *cdph_p = (struct libnet_cdp_hdr *)buf; cdph_p->cdp_sum = 0; sum = libnet_in_cksum((u_int16_t *)cdph_p, len); cdph_p->cdp_sum = LIBNET_CKSUM_CARRY(sum); break; } case LIBNET_PROTO_ISL: { // struct libnet_isl_hdr *islh_p = // (struct libnet_isl_hdr *)buf; /* * Need to compute 4 byte CRC for the ethernet frame and for * the ISL frame itself. Use the libnet_crc function. */ } default: { snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): unsuported protocol %d\n", __func__, protocol); return (-1); } } return (1); }
int update_TSUM(libnet_t *l, libnet_ptag_t t) { int sum = 0; unsigned int tmp; if (tx.tcp_sum != 0) return 0; sum += libnet_in_cksum((u_int16_t *) &tx.ip6_src, 16); if (tx.ip_option_s && tx.ip6_segs) sum += libnet_in_cksum((u_int16_t *) &tx.ip_option[tx.ip_option_s - 16], 16); // Use last IP address else sum += libnet_in_cksum((u_int16_t *) &tx.ip6_dst, 16); tmp = htonl(tx.tcp_len); sum += libnet_in_cksum((u_int16_t *) &tmp, 4); tmp = htonl(IPPROTO_TCP); sum += libnet_in_cksum((u_int16_t *) &tmp, 4); tmp = ((htons(tx.sp) << 16) + htons(tx.dp)); sum += libnet_in_cksum((u_int16_t *) &tmp, 4); tmp = htonl(tx.tcp_seq); sum += libnet_in_cksum((u_int16_t *) &tmp, 4); tmp = htonl(tx.tcp_ack); sum += libnet_in_cksum((u_int16_t *) &tmp, 4); tmp = ((ntohs(((tx.tcp_offset) << 12) + tx.tcp_control) << 16) + htons(tx.tcp_win)); sum += libnet_in_cksum((u_int16_t *) &tmp, 4); tmp = htonl(tx.tcp_urg); sum += libnet_in_cksum((u_int16_t *) &tmp, 4); sum += tx.tcp_sum_part; if (tx.tcp_payload_s) sum += libnet_in_cksum((u_int16_t *) tx.tcp_payload, tx.tcp_payload_s); tx.tcp_sum = ntohs(LIBNET_CKSUM_CARRY(sum)); t = libnet_build_tcp (tx.sp, tx.dp, tx.tcp_seq, tx.tcp_ack, tx.tcp_control, tx.tcp_win, tx.tcp_sum, tx.tcp_urg, tx.tcp_len, tx.tcp_payload_s ? tx.tcp_payload : NULL, tx.tcp_payload_s, l, t); return t; }
int libnet_do_checksum(u_char *buf, int protocol, int len) { struct libnet_ip_hdr *iph_p; int ip_hl; int sum; sum = 0; iph_p = (struct libnet_ip_hdr *)buf; ip_hl = iph_p->ip_hl << 2; /* * Dug Song came up with this very cool checksuming implementation * eliminating the need for explicit psuedoheader use. Check it out. */ switch (protocol) { /* * Style note: normally I don't advocate declaring variables inside * blocks of control, but it makes good sense here. -- MDS */ case IPPROTO_TCP: { struct libnet_tcp_hdr *tcph_p = (struct libnet_tcp_hdr *)(buf + ip_hl); #if (STUPID_SOLARIS_CHECKSUM_BUG) tcph_p->th_sum = tcph_p->th_off << 2; return (1); #endif /* STUPID_SOLARIS_CHECKSUM_BUG */ tcph_p->th_sum = 0; sum = libnet_in_cksum((u_short *)&iph_p->ip_src, 8); sum += ntohs(IPPROTO_TCP + len); sum += libnet_in_cksum((u_short *)tcph_p, len); tcph_p->th_sum = LIBNET_CKSUM_CARRY(sum); break; } case IPPROTO_UDP: { struct libnet_udp_hdr *udph_p = (struct libnet_udp_hdr *)(buf + ip_hl); udph_p->uh_sum = 0; sum = libnet_in_cksum((u_short *)&iph_p->ip_src, 8); sum += ntohs(IPPROTO_UDP + len); sum += libnet_in_cksum((u_short *)udph_p, len); udph_p->uh_sum = LIBNET_CKSUM_CARRY(sum); break; } case IPPROTO_ICMP: { struct libnet_icmp_hdr *icmph_p = (struct libnet_icmp_hdr *)(buf + ip_hl); icmph_p->icmp_sum = 0; sum = libnet_in_cksum((u_short *)icmph_p, len); icmph_p->icmp_sum = LIBNET_CKSUM_CARRY(sum); break; } case IPPROTO_IGMP: { struct libnet_igmp_hdr *igmph_p = (struct libnet_igmp_hdr *)(buf + ip_hl); igmph_p->igmp_sum = 0; sum += libnet_in_cksum((u_short *)igmph_p, len); igmph_p->igmp_sum = LIBNET_CKSUM_CARRY(sum); break; } case IPPROTO_OSPF: { struct libnet_ospf_hdr *oh_p = (struct libnet_ospf_hdr *)(buf + ip_hl); u_char *payload = (u_char *)(buf + ip_hl + LIBNET_AUTH_H + sizeof(oh_p)); u_char *tbuf = (u_char *)malloc(sizeof(oh_p) + sizeof(payload)); oh_p->ospf_cksum = 0; sum += libnet_in_cksum((u_short *)tbuf, sizeof(tbuf)); oh_p->ospf_cksum = LIBNET_CKSUM_CARRY(sum); free(tbuf); break; } case IPPROTO_OSPF_LSA: { /* * Reworked fletcher checksum taken from RFC 1008. */ int c0, c1; struct libnet_lsa_hdr *lsa_p = (struct libnet_lsa_hdr *)buf; u_char *p, *p1, *p2, *p3; c0 = 0; c1 = 0; lsa_p->lsa_cksum[0] = 0; lsa_p->lsa_cksum[1] = 0; /* zero out checksum */ p = buf; p1 = buf; p3 = buf + len; /* beginning and end of buf */ while (p1 < p3) { p2 = p1 + LIBNET_MODX; if (p2 > p3) { p2 = p3; } for (p = p1; p < p2; p++) { c0 += (*p); c1 += c0; } c0 %= 255; c1 %= 255; /* modular 255 */ p1 = p2; } lsa_p->lsa_cksum[0] = (((len - 17) * c0 - c1) % 255); if (lsa_p->lsa_cksum[0] <= 0) { lsa_p->lsa_cksum[0] += 255; } lsa_p->lsa_cksum[1] = (510 - c0 - lsa_p->lsa_cksum[0]); if (lsa_p->lsa_cksum[1] > 255) { lsa_p->lsa_cksum[1] -= 255; } break; } case IPPROTO_IP: { iph_p->ip_sum = 0; sum = libnet_in_cksum((u_short *)iph_p, len); iph_p->ip_sum = LIBNET_CKSUM_CARRY(sum); break; } default: { #if (__DEBUG) libnet_error(LN_ERR_CRITICAL, "do_checksum: UNSUPP protocol %d\n", protocol); #endif return (-1); } } return (1); }
/* * We are checksumming pblock "q" * * iphdr is the pointer to it's encapsulating IP header * protocol describes the type of "q", expressed as an IPPROTO_ value * h_len is the h_len from "q" */ int libnet_inet_checksum(libnet_t *l, uint8_t *iphdr, int protocol, int h_len, const uint8_t *beg, const uint8_t * end) { /* will need to update this for ipv6 at some point */ struct libnet_ipv4_hdr *iph_p = (struct libnet_ipv4_hdr *)iphdr; struct libnet_ipv6_hdr *ip6h_p = NULL; /* default to not using IPv6 */ int ip_hl = 0; int sum = 0; /* Check for memory under/over reads/writes. */ if(iphdr < beg || (iphdr+sizeof(*iph_p)) > end) { snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): ipv4 hdr not inside packet (where %d, size %d)\n", __func__, (int)(iphdr-beg), (int)(end-beg)); return -1; } /* * Figure out which IP version we're dealing with. We'll assume v4 * and overlay a header structure to yank out the version. */ if (iph_p->ip_v == 6) { ip6h_p = (struct libnet_ipv6_hdr *)iph_p; iph_p = NULL; ip_hl = 40; if((uint8_t*)(ip6h_p+1) > end) { snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): ipv6 hdr not inside packet\n", __func__); return -1; } } else { ip_hl = iph_p->ip_hl << 2; } if((iphdr+ip_hl) > end) { snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): ip hdr len not inside packet\n", __func__); return -1; } /* * Dug Song came up with this very cool checksuming implementation * eliminating the need for explicit psuedoheader use. Check it out. */ switch (protocol) { case IPPROTO_TCP: { struct libnet_tcp_hdr *tcph_p = (struct libnet_tcp_hdr *)(iphdr + ip_hl); h_len = end - (uint8_t*) tcph_p; /* ignore h_len, sum the packet we've coalesced */ CHECK_IP_PAYLOAD_SIZE(); #if (STUPID_SOLARIS_CHECKSUM_BUG) tcph_p->th_sum = tcph_p->th_off << 2; return (1); #endif /* STUPID_SOLARIS_CHECKSUM_BUG */ #if (HAVE_HPUX11) if (l->injection_type != LIBNET_LINK) { /* * Similiar to the Solaris Checksum bug - but need to add * the size of the TCP payload (only for raw sockets). */ tcph_p->th_sum = (tcph_p->th_off << 2) + (h_len - (tcph_p->th_off << 2)); return (1); } #endif /* TCP checksum is over the IP pseudo header: * ip src * ip dst * tcp protocol (IPPROTO_TCP) * tcp length, including the header * + the TCP header (with checksum set to zero) and data */ tcph_p->th_sum = 0; if (ip6h_p) { sum = libnet_in_cksum((uint16_t *)&ip6h_p->ip_src, 32); } else { /* 8 = src and dst */ sum = libnet_in_cksum((uint16_t *)&iph_p->ip_src, 8); } sum += ntohs(IPPROTO_TCP + h_len); sum += libnet_in_cksum((uint16_t *)tcph_p, h_len); tcph_p->th_sum = LIBNET_CKSUM_CARRY(sum); #if 0 printf("tcp sum calculated: %#x/%d h_len %d\n", ntohs(tcph_p->th_sum), ntohs(tcph_p->th_sum), h_len ); #endif break; } case IPPROTO_UDP: { struct libnet_udp_hdr *udph_p = (struct libnet_udp_hdr *)(iphdr + ip_hl); h_len = end - (uint8_t*) udph_p; /* ignore h_len, sum the packet we've coalesced */ CHECK_IP_PAYLOAD_SIZE(); udph_p->uh_sum = 0; if (ip6h_p) { sum = libnet_in_cksum((uint16_t *)&ip6h_p->ip_src, 32); } else { sum = libnet_in_cksum((uint16_t *)&iph_p->ip_src, 8); } sum += ntohs(IPPROTO_UDP + h_len); sum += libnet_in_cksum((uint16_t *)udph_p, h_len); udph_p->uh_sum = LIBNET_CKSUM_CARRY(sum); break; } case IPPROTO_ICMP: { struct libnet_icmpv4_hdr *icmph_p = (struct libnet_icmpv4_hdr *)(iphdr + ip_hl); h_len = end - (uint8_t*) icmph_p; /* ignore h_len, sum the packet we've coalesced */ CHECK_IP_PAYLOAD_SIZE(); icmph_p->icmp_sum = 0; /* Hm, is this valid? Is the checksum algorithm for ICMPv6 encapsulated in IPv4 * actually defined? */ if (ip6h_p) { sum = libnet_in_cksum((uint16_t *)&ip6h_p->ip_src, 32); sum += ntohs(IPPROTO_ICMP6 + h_len); } sum += libnet_in_cksum((uint16_t *)icmph_p, h_len); icmph_p->icmp_sum = LIBNET_CKSUM_CARRY(sum); break; } case IPPROTO_ICMPV6: { struct libnet_icmpv6_hdr *icmph_p = (struct libnet_icmpv6_hdr *)(iphdr + ip_hl); h_len = end - (uint8_t*) icmph_p; /* ignore h_len, sum the packet we've coalesced */ CHECK_IP_PAYLOAD_SIZE(); icmph_p->icmp_sum = 0; if (ip6h_p) { sum = libnet_in_cksum((uint16_t *)&ip6h_p->ip_src, 32); sum += ntohs(IPPROTO_ICMP6 + h_len); } sum += libnet_in_cksum((uint16_t *)icmph_p, h_len); icmph_p->icmp_sum = LIBNET_CKSUM_CARRY(sum); break; } case IPPROTO_IGMP: { struct libnet_igmp_hdr *igmph_p = (struct libnet_igmp_hdr *)(iphdr + ip_hl); h_len = end - (uint8_t*) igmph_p; /* ignore h_len, sum the packet we've coalesced */ CHECK_IP_PAYLOAD_SIZE(); igmph_p->igmp_sum = 0; sum = libnet_in_cksum((uint16_t *)igmph_p, h_len); igmph_p->igmp_sum = LIBNET_CKSUM_CARRY(sum); break; } case IPPROTO_GRE: { /* checksum is always at the same place in GRE header * in the multiple RFC version of the protocol ... ouf !!! */ struct libnet_gre_hdr *greh_p = (struct libnet_gre_hdr *)(iphdr + ip_hl); uint16_t fv = ntohs(greh_p->flags_ver); CHECK_IP_PAYLOAD_SIZE(); if (!(fv & (GRE_CSUM|GRE_ROUTING | GRE_VERSION_0)) || !(fv & (GRE_CSUM|GRE_VERSION_1))) { snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): can't compute GRE checksum (wrong flags_ver bits: 0x%x )\n", __func__, fv); return (-1); } sum = libnet_in_cksum((uint16_t *)greh_p, h_len); greh_p->gre_sum = LIBNET_CKSUM_CARRY(sum); break; } case IPPROTO_OSPF: { struct libnet_ospf_hdr *oh_p = (struct libnet_ospf_hdr *)(iphdr + ip_hl); CHECK_IP_PAYLOAD_SIZE(); oh_p->ospf_sum = 0; sum += libnet_in_cksum((uint16_t *)oh_p, h_len); oh_p->ospf_sum = LIBNET_CKSUM_CARRY(sum); break; } case IPPROTO_OSPF_LSA: { struct libnet_ospf_hdr *oh_p = (struct libnet_ospf_hdr *)(iphdr + ip_hl); struct libnet_lsa_hdr *lsa_p = (struct libnet_lsa_hdr *)(iphdr + ip_hl + oh_p->ospf_len); /* FIXME need additional length check, to account for ospf_len */ lsa_p->lsa_sum = 0; sum += libnet_in_cksum((uint16_t *)lsa_p, h_len); lsa_p->lsa_sum = LIBNET_CKSUM_CARRY(sum); break; #if 0 /* * Reworked fletcher checksum taken from RFC 1008. */ int c0, c1; struct libnet_lsa_hdr *lsa_p = (struct libnet_lsa_hdr *)buf; uint8_t *p, *p1, *p2, *p3; c0 = 0; c1 = 0; lsa_p->lsa_cksum = 0; p = buf; p1 = buf; p3 = buf + len; /* beginning and end of buf */ while (p1 < p3) { p2 = p1 + LIBNET_MODX; if (p2 > p3) { p2 = p3; } for (p = p1; p < p2; p++) { c0 += (*p); c1 += c0; } c0 %= 255; c1 %= 255; /* modular 255 */ p1 = p2; } #if AWR_PLEASE_REWORK_THIS lsa_p->lsa_cksum[0] = (((len - 17) * c0 - c1) % 255); if (lsa_p->lsa_cksum[0] <= 0) { lsa_p->lsa_cksum[0] += 255; } lsa_p->lsa_cksum[1] = (510 - c0 - lsa_p->lsa_cksum[0]); if (lsa_p->lsa_cksum[1] > 255) { lsa_p->lsa_cksum[1] -= 255; } #endif break; #endif } case IPPROTO_IP: { if(!iph_p) { /* IPv6 doesn't have a checksum */ } else { iph_p->ip_sum = 0; sum = libnet_in_cksum((uint16_t *)iph_p, ip_hl); iph_p->ip_sum = LIBNET_CKSUM_CARRY(sum); } break; } case IPPROTO_VRRP: { struct libnet_vrrp_hdr *vrrph_p = (struct libnet_vrrp_hdr *)(iphdr + ip_hl); CHECK_IP_PAYLOAD_SIZE(); vrrph_p->vrrp_sum = 0; sum = libnet_in_cksum((uint16_t *)vrrph_p, h_len); vrrph_p->vrrp_sum = LIBNET_CKSUM_CARRY(sum); break; } case LIBNET_PROTO_CDP: { /* XXX - Broken: how can we easily get the entire packet size? */ /* FIXME you can't, checksumming non-IP protocols was not supported by libnet */ struct libnet_cdp_hdr *cdph_p = (struct libnet_cdp_hdr *)iphdr; if((iphdr+h_len) > end) { snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): cdp payload not inside packet\n", __func__); return -1; } cdph_p->cdp_sum = 0; sum = libnet_in_cksum((uint16_t *)cdph_p, h_len); cdph_p->cdp_sum = LIBNET_CKSUM_CARRY(sum); break; } case LIBNET_PROTO_ISL: { #if 0 struct libnet_isl_hdr *islh_p = (struct libnet_isl_hdr *)buf; #endif /* * Need to compute 4 byte CRC for the ethernet frame and for * the ISL frame itself. Use the libnet_crc function. */ } default: { snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): unsupported protocol %d\n", __func__, protocol); return (-1); } } return (1); }
int main(int argc, char* argv[]) { if ( argc<4 ) { usage(argv[0]); return EXIT_FAILURE; } int retVal; struct addrinfo hints,*addrinfo; ZeroMemory(&hints,sizeof(hints)); WSADATA wsaData; if ( WSAStartup( MAKEWORD(2,2), &wsaData ) != NO_ERROR ) { fprintf( stderr, "Error in WSAStartup():%d\n",WSAGetLastError()); return EXIT_FAILURE; } // // Get MAC address of remote host (assume link local IpV6 address) // hints.ai_family = PF_INET6; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; hints.ai_flags = AI_PASSIVE; retVal = getaddrinfo(argv[2],0, &hints, &addrinfo); if ( retVal!=0 ) { WSACleanup(); fprintf( stderr, "Error in getaddrinfo():%d\n",WSAGetLastError()); exit(EXIT_FAILURE); } // // Open WinPCap adapter // if ( (pcap_handle = pcap_open_live (argv[1], 1514, PCAP_OPENFLAG_PROMISCUOUS, 100, (char*)errbuf)) == NULL ) { freeaddrinfo(addrinfo); WSACleanup(); fprintf(stderr, "Error opening device: %s\n",argv[1]); return EXIT_FAILURE; } ZeroMemory(packet,sizeof(packet)); struct sockaddr_in6 *sa = (struct sockaddr_in6 *) addrinfo->ai_addr; // fill ethernet header eth_hdr->ether_dhost[0] = eth_hdr->ether_shost[0] = 0;// assume address like 00:something; eth_hdr->ether_dhost[1] = eth_hdr->ether_shost[1] = sa->sin6_addr.u.Byte[9]; eth_hdr->ether_dhost[2] = eth_hdr->ether_shost[2] = sa->sin6_addr.u.Byte[10]; eth_hdr->ether_dhost[3] = eth_hdr->ether_shost[3] = sa->sin6_addr.u.Byte[13]; eth_hdr->ether_dhost[4] = eth_hdr->ether_shost[4] = sa->sin6_addr.u.Byte[14]; eth_hdr->ether_dhost[5] = eth_hdr->ether_shost[5] = sa->sin6_addr.u.Byte[15]; eth_hdr->ether_type = 0xdd86; // fill IP header // source ip == destination ip memcpy(ip6_hdr->ip_src.__u6_addr.__u6_addr8,sa->sin6_addr.u.Byte,sizeof(sa->sin6_addr.u.Byte)); memcpy(ip6_hdr->ip_dst.__u6_addr.__u6_addr8,sa->sin6_addr.u.Byte,sizeof(sa->sin6_addr.u.Byte)); ip6_hdr->ip_hl = 255; ip6_hdr->ip_nh = IPPROTO_TCP; ip6_hdr->ip_len = htons (20); ip6_hdr->ip_flags[0] = 0x06 << 4; srand((unsigned int) time(0)); // fill tcp header tcp_hdr->th_sport = tcp_hdr->th_dport = htons (atoi(argv[3])); // source port equal to destination tcp_hdr->th_seq = rand(); tcp_hdr->th_ack = rand(); tcp_hdr->th_off = htons(5); tcp_hdr->th_win = rand(); tcp_hdr->th_sum = 0; tcp_hdr->th_urp = htons(10); tcp_hdr->th_off = 5; tcp_hdr->th_flags = 2; // calculate tcp checksum int chsum = libnet_in_cksum ((u_int16_t *) & ip6_hdr->ip_src, 32); chsum += ntohs (IPPROTO_TCP + sizeof (struct libnet_tcp_hdr)); chsum += libnet_in_cksum ((u_int16_t *) tcp_hdr, sizeof (struct libnet_tcp_hdr)); tcp_hdr->th_sum = LIBNET_CKSUM_CARRY (chsum); // send data to wire retVal = pcap_sendpacket (pcap_handle, (u_char *) packet, sizeof(packet)); if ( retVal == -1 ) { fprintf(stderr,"Error writing packet to wire!!\n"); } // // close adapter, free mem.. etc.. // pcap_close(pcap_handle); freeaddrinfo(addrinfo); WSACleanup(); return EXIT_SUCCESS; }
/* ipsec_output() from driver-core */ int ipsec_output( void* Adapter, struct pkt_buff *pktb ) { PIPSEC pIpsec=&((pADAPTER)Adapter)->Ipsec_SL.Ipsec; struct ipsec_output_state state; struct ip *ip; int ret; u_char *buf; int out_len; /*printk(KERN_ERR "-----------------ipsec_output-------------------\n");*/ DBG_ENTER(ipsec_output); /* PMC-Viana-011-カーネルログ出力有効/無効切り替え対応 add start */ #ifdef BUILD_ANDROID TNC_LOGOUT("Call ipsec_output \n"); #endif /* BUILD_ANDROID */ /* PMC-Viana-011-カーネルログ出力有効/無効切り替え対応 add end */ if( !pIpsec->init ) { /* PMC-Viana-011-カーネルログ出力有効/無効切り替え対応 add start */ #ifdef BUILD_ANDROID TNC_LOGOUT(KERN_ERR "ipsec_core Don't initialize\n"); #else /* BUILD_ANDROID */ printk(KERN_ERR "ipsec_core Don't initialize\n"); #endif /* BUILD_ANDROID */ /* PMC-Viana-011-カーネルログ出力有効/無効切り替え対応 add end */ return(0); } ip = (struct ip *)pktb->data; /* PMC-Viana-011-カーネルログ出力有効/無効切り替え対応 add start */ #ifdef BUILD_ANDROID TNC_LOGOUT(KERN_ERR "Call ipsec_output \n"); TNC_LOGOUT(KERN_ERR "host: 0x%x\n",(u_int)ip->ip_dst.s_addr); TNC_LOGOUT(KERN_ERR "pIpsec->dst_ip: 0x%x\n",(u_int)pIpsec->dst_ip); #endif /* BUILD_ANDROID */ /* PMC-Viana-011-カーネルログ出力有効/無効切り替え対応 add end */ if( pIpsec->dst_ip != (ip->ip_dst.s_addr & pIpsec->dst_mask) ) { /* PMC-Viana-011-カーネルログ出力有効/無効切り替え対応 add start */ #ifdef BUILD_ANDROID TNC_LOGOUT(KERN_ERR "Unknown host: IPSEC_DST=0x%x IP_DST=0x%x IPSEC_MASK=0x%x\n", (u_int)pIpsec->dst_ip, (u_int)ip->ip_dst.s_addr, (u_int)pIpsec->dst_mask); #else /* BUILD_ANDROID */ printk(KERN_ERR "Unknown host: IPSEC_DST=0x%x IP_DST=0x%x IPSEC_MASK=0x%x\n", (u_int)pIpsec->dst_ip, (u_int)ip->ip_dst.s_addr, (u_int)pIpsec->dst_mask); #endif /* BUILD_ANDROID */ /* PMC-Viana-011-カーネルログ出力有効/無効切り替え対応 add end */ /* そのまま送信するのか? それともエラーとして捨てるのか?*/ return(-1); } state.m = out_state_set( pIpsec, pktb->data, pktb->len, &state ); if(state.m == NULL) { DBGPRINT(("Faile to get mbuf at out_state_set\n")); return -1; } ret = ipsec4_output( pIpsec, &state ); if( ret < 0 ) { return( ret ); } if( ret == 1 ) { buf = restore_mbuf( state.m, &out_len ); #ifdef notdef /* AH Tunnel bug -> move */ ip = (struct ip *)buf; if (pIpsec->def_isr.saidx.mode == IPSEC_MODE_TUNNEL) { ip->ip_dst.s_addr = pIpsec->tun_dst; ip->ip_src.s_addr = pIpsec->tun_src; } hlen = ip->ip_hl << 2; ip->ip_sum = 0; /* make ip checksum */ sum = libnet_in_cksum((u_short *)ip, hlen); ip->ip_sum = (u_short)(LIBNET_CKSUM_CARRY(sum)); #endif if(((UINT)out_len > pktb->buff_len) || ((UINT)(buf + out_len) > (UINT)pktb->end)) { DbgPrint("out_len:%d,pktb->buff_len:%d, (buf + out_len):%x,pktb->end:%x\n", out_len, pktb->buff_len, (UINT)(buf + out_len), (u_int)pktb->end); return -1; } if(pktb->head > buf) { DBGPRINT("pktb->head:%x,buf:%x\n", (u_int)pktb->head, (u_int)buf); return -1; } pktb->len = out_len; pktb->data = buf; pktb->tail = pktb->data+pktb->len; } return( ret ); }