diff options
Diffstat (limited to 'extras/libmemif/examples/icmp_responder/icmp_proto.c')
-rw-r--r-- | extras/libmemif/examples/icmp_responder/icmp_proto.c | 524 |
1 files changed, 0 insertions, 524 deletions
diff --git a/extras/libmemif/examples/icmp_responder/icmp_proto.c b/extras/libmemif/examples/icmp_responder/icmp_proto.c deleted file mode 100644 index 785aebd5567..00000000000 --- a/extras/libmemif/examples/icmp_responder/icmp_proto.c +++ /dev/null @@ -1,524 +0,0 @@ -/* - *------------------------------------------------------------------ - * Copyright (c) 2017 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------ - */ - -#include <stdint.h> -#include <net/if.h> -#include <sys/types.h> -#include <fcntl.h> -#include <sys/ioctl.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <sys/uio.h> -#include <sys/mman.h> -#include <sys/prctl.h> -#include <inttypes.h> -#include <string.h> -#include <stdio.h> -#include <netdb.h> -#include <linux/ip.h> -#include <linux/icmp.h> -#include <arpa/inet.h> -#include <stdlib.h> -#include <netinet/if_ether.h> -#include <net/if_arp.h> -#include <asm/byteorder.h> -#include <byteswap.h> -#include <assert.h> - -#include <icmp_proto.h> - -static uint16_t -cksum (void *addr, ssize_t len) -{ - char *data = (char *) addr; - - uint32_t acc = 0xffff; - - ssize_t i; - for (i = 0; (i + 1) < len; i += 2) - { - uint16_t word; - memcpy (&word, data + i, 2); - acc += ntohs (word); - if (acc > 0xffff) - acc -= 0xffff; - } - - if (len & 1) - { - uint16_t word = 0; - memcpy (&word, data + len - 1, 1); - acc += ntohs (word); - if (acc > 0xffff) - acc -= 0xffff; - } - return htons (~acc); -} - -int -print_packet (void *pck) -{ - if (pck == NULL) - { - printf ("ICMP_PROTO: no data\n"); - return -1; - } - struct iphdr *ip; - struct icmphdr *icmp; - ip = (struct iphdr *) pck; - icmp = (struct icmphdr *) (pck + sizeof (struct iphdr)); - printf ("received packet:\n"); - printf ("\tiphdr:\n"); - printf ("\t\tihl: %u\n\t\tversion: %u\n\t\tlen: %u\n\t\tid: %u\n", - ip->ihl, ip->version, __bswap_16 (ip->tot_len), ip->id); - printf ("\t\tprotocol: %u\n", ip->protocol); - - printf ("\t\tsaddr: "); - int i; - for (i = 0; i < 4; i++) - { - printf ("%u.", ((uint8_t *) & ip->saddr)[i]); - } - printf ("\n"); - - printf ("\t\tdaddr: "); - for (i = 0; i < 4; i++) - { - printf ("%u.", ((uint8_t *) & ip->daddr)[i]); - } - printf ("\n"); - printf ("\ticmphdr:\n"); - printf ("\t\ttype: %s\n", - (icmp->type == ICMP_ECHO) ? "ICMP_ECHO" : "ICMP_ECHOREPLY"); - - return 0; -} - -static ssize_t -resolve_arp (void *arp) -{ - struct arphdr *resp = (struct arphdr *) arp; - - resp->ar_hrd = __bswap_16 (ARPHRD_ETHER); - - resp->ar_pro = __bswap_16 (0x0800); - - resp->ar_hln = 6; - resp->ar_pln = 4; - - resp->ar_op = __bswap_16 (ARPOP_REPLY); - - return sizeof (struct arphdr); -} - -static ssize_t -resolve_eth_arp (struct ether_arp *eth_arp, void *eth_arp_resp, - uint8_t ip_addr[4]) -{ - struct ether_arp *resp = (struct ether_arp *) eth_arp_resp; - - resolve_arp (&resp->ea_hdr); - - memcpy (resp->arp_tha, eth_arp->arp_sha, 6); - memcpy (resp->arp_tpa, eth_arp->arp_spa, 4); - - memcpy (resp->arp_sha, - (((struct ether_header *) (eth_arp_resp - - sizeof (struct - ether_header)))->ether_shost), - 6); - - memcpy (resp->arp_spa, ip_addr, 4); - - return sizeof (struct ether_arp); -} - -static ssize_t -resolve_eth (struct ether_header *eth, void *eth_resp) -{ - struct ether_header *resp = (struct ether_header *) eth_resp; - memcpy (resp->ether_dhost, eth->ether_shost, 6); - - uint8_t hw_addr[6]; - int i; - for (i = 0; i < 6; i++) - { - hw_addr[i] = 'a'; - } - memcpy (resp->ether_shost, hw_addr, 6); - - resp->ether_type = eth->ether_type; - - return sizeof (struct ether_header); -} - -static ssize_t -resolve_ip (struct iphdr *ip, void *ip_resp, uint8_t ip_addr[4]) -{ - struct iphdr *resp = (struct iphdr *) ip_resp; - resp->ihl = 5; - resp->version = 4; - resp->tos = 0; - /*len updated later */ - resp->tot_len = 0x0000; - resp->id = 0; - resp->frag_off = 0; - resp->ttl = 0x40; - resp->protocol = 1; - ((uint8_t *) & resp->saddr)[0] = ip_addr[0]; - ((uint8_t *) & resp->saddr)[1] = ip_addr[1]; - ((uint8_t *) & resp->saddr)[2] = ip_addr[2]; - ((uint8_t *) & resp->saddr)[3] = ip_addr[3]; - resp->daddr = ip->saddr; - - /* resp->check = cksum (resp, sizeof (struct iphdr)); */ - - return sizeof (struct iphdr); -} - -static ssize_t -resolve_icmp (struct icmphdr *icmp, void *icmp_resp) -{ - struct icmphdr *resp = (struct icmphdr *) icmp_resp; - resp->type = 0x00; - resp->code = 0; - resp->un.echo.id = icmp->un.echo.id; - resp->un.echo.sequence = icmp->un.echo.sequence; - - /*resp->checksum = cksum (resp, sizeof (struct icmphdr)); */ - - return sizeof (struct icmphdr); -} - -int -resolve_packet (void *in_pck, ssize_t in_size, - void *out_pck, uint32_t * out_size, uint8_t ip_addr[4]) -{ - struct ether_header *eh; - struct ether_arp *eah; - struct iphdr *ip, *ip_out; - struct icmphdr *icmp; - *out_size = 0; - - if ((in_pck == NULL) || (out_pck == NULL)) - return -1; - - eh = (struct ether_header *) in_pck; - *out_size = resolve_eth (eh, out_pck); - - if (eh->ether_type == 0x0608) - { - eah = (struct ether_arp *) (in_pck + *out_size); - *out_size += resolve_eth_arp (eah, out_pck + *out_size, ip_addr); - - } - else if (eh->ether_type == 0x0008) - { -#ifdef ICMP_DBG - print_packet (in_pck + *out_size); -#endif - ip = (struct iphdr *) (in_pck + *out_size); - ip_out = (struct iphdr *) (out_pck + *out_size); - *out_size += resolve_ip (ip, out_pck + *out_size, ip_addr); - if (ip->protocol == 1) - { - icmp = (struct icmphdr *) (in_pck + *out_size); - *out_size += resolve_icmp (icmp, out_pck + *out_size); - ((struct icmphdr *) (out_pck + *out_size - - sizeof (struct icmphdr)))->checksum = - cksum (out_pck + *out_size - sizeof (struct icmphdr), - sizeof (struct icmphdr)); - /* payload */ - memcpy (out_pck + *out_size, in_pck + *out_size, - in_size - *out_size); - *out_size = in_size; - ip_out->tot_len = - __bswap_16 (*out_size - sizeof (struct ether_header)); - ip_out->check = cksum (ip_out, sizeof (struct iphdr)); - } - } - return 0; -} - -static ssize_t -generate_eth (struct ether_header *eh, uint8_t hw_daddr[6]) -{ - uint8_t hw_addr[6]; - int i; - for (i = 0; i < 6; i++) - { - hw_addr[i] = 'a'; - } - memcpy (eh->ether_shost, hw_addr, 6); - memcpy (eh->ether_dhost, hw_daddr, 6); - - eh->ether_type = 0x0008; - - return sizeof (struct ether_header); -} - -static ssize_t -generate_ip (struct iphdr *ip, uint8_t saddr[4], uint8_t daddr[4]) -{ - ip->ihl = 5; - ip->version = 4; - ip->tos = 0; - /*len updated later */ - ip->tot_len = 0x5400; - ip->id = 0; - ip->frag_off = 0; - ip->ttl = 0x40; - ip->protocol = 1; - /* saddr */ - ((uint8_t *) & ip->saddr)[0] = saddr[0]; - ((uint8_t *) & ip->saddr)[1] = saddr[1]; - ((uint8_t *) & ip->saddr)[2] = saddr[2]; - ((uint8_t *) & ip->saddr)[3] = saddr[3]; - /* daddr */ - ((uint8_t *) & ip->daddr)[0] = daddr[0]; - ((uint8_t *) & ip->daddr)[1] = daddr[1]; - ((uint8_t *) & ip->daddr)[2] = daddr[2]; - ((uint8_t *) & ip->daddr)[3] = daddr[3]; - - ip->check = cksum (ip, sizeof (struct iphdr)); - - return sizeof (struct iphdr); -} - -static ssize_t -generate_icmp (struct icmphdr *icmp, uint32_t seq) -{ - icmp->type = ICMP_ECHO; - icmp->code = 0; - icmp->un.echo.id = 0; - icmp->un.echo.sequence = seq; - - return sizeof (struct icmphdr); -} - -int -generate_packet (void *pck, uint32_t * size, uint8_t saddr[4], - uint8_t daddr[4], uint8_t hw_daddr[6], uint32_t seq) -{ - struct ether_header *eh; - struct iphdr *ip; - struct icmphdr *icmp; - - *size = 0; - - eh = (struct ether_header *) pck; - *size += generate_eth (eh, hw_daddr); - - ip = (struct iphdr *) (pck + *size); - *size += generate_ip (ip, saddr, daddr); - - icmp = (struct icmphdr *) (pck + *size); - *size += generate_icmp (icmp, seq); - - ((struct icmphdr *) (pck + *size - sizeof (struct icmphdr)))->checksum = - cksum (pck + *size - sizeof (struct icmphdr), sizeof (struct icmphdr)); - - ip->tot_len = __bswap_16 (*size - sizeof (struct ether_header)); - ip->check = 0; - ip->check = cksum (ip, sizeof (struct iphdr)); - - return 0; -} - -int -generate_packet2 (void *pck, uint32_t * size, uint8_t saddr[4], - uint8_t daddr[4], uint8_t hw_daddr[6], uint32_t seq, - icmpr_flow_mode_t mode) -{ - struct ether_header *eh; - struct iphdr *ip; - struct icmphdr *icmp; - - *size = 0; - - if (mode == ICMPR_FLOW_MODE_ETH) - { - eh = (struct ether_header *) pck; - *size += generate_eth (eh, hw_daddr); - } - - ip = (struct iphdr *) (pck + *size); - *size += generate_ip (ip, saddr, daddr); - - icmp = (struct icmphdr *) (pck + *size); - *size += generate_icmp (icmp, seq); - - ((struct icmphdr *) (pck + *size - sizeof (struct icmphdr)))->checksum = - cksum (pck + *size - sizeof (struct icmphdr), sizeof (struct icmphdr)); - - ip->tot_len = __bswap_16 (*size - sizeof (struct ether_header)); - ip->check = 0; - ip->check = cksum (ip, sizeof (struct iphdr)); - - return 0; -} - -#define GET_HEADER(out,hdr,src,off) do { \ - out = (hdr*)(src + off); \ - off += sizeof (hdr); \ - } while (0) - -int -resolve_packet2 (void *pck, uint32_t * size, uint8_t ip_addr[4]) -{ - struct ether_header *eh; - struct ether_arp *eah; - struct iphdr *ip; - struct icmphdr *icmp; - uint32_t offset = 0; - - if (pck == NULL) - return 0; - - GET_HEADER (eh, struct ether_header, pck, offset); - - memcpy (eh->ether_dhost, eh->ether_shost, 6); - memcpy (eh->ether_shost, "aaaaaa", 6); - - if (eh->ether_type == 0x0608) - { - GET_HEADER (eah, struct ether_arp, pck, offset); - struct arphdr *arp = &eah->ea_hdr; - - arp->ar_hrd = __bswap_16 (ARPHRD_ETHER); - arp->ar_pro = __bswap_16 (0x0800); - - arp->ar_hln = 6; - arp->ar_pln = 4; - - arp->ar_op = __bswap_16 (ARPOP_REPLY); - - memcpy (eah->arp_tha, eah->arp_sha, 6); - memcpy (eah->arp_tpa, eah->arp_spa, 4); - - memcpy (eah->arp_sha, eh->ether_shost, 6); - memcpy (eah->arp_spa, ip_addr, 4); - } - - else if (eh->ether_type == 0x0008) - { - GET_HEADER (ip, struct iphdr, pck, offset); - - if (ip->protocol == 1) - { - ip->ihl = 5; - ip->version = 4; - ip->tos = 0; - ip->tot_len = 0x0000; - ip->id = 0; - ip->frag_off = 0; - ip->ttl = 0x40; - ip->protocol = 1; - ip->check = 0x0000; - ip->daddr = ip->saddr; - ((uint8_t *) & ip->saddr)[0] = ip_addr[0]; - ((uint8_t *) & ip->saddr)[1] = ip_addr[1]; - ((uint8_t *) & ip->saddr)[2] = ip_addr[2]; - ((uint8_t *) & ip->saddr)[3] = ip_addr[3]; - - GET_HEADER (icmp, struct icmphdr, pck, offset); - - icmp->type = 0x00; - icmp->code = 0; - icmp->checksum = cksum (icmp, sizeof (struct icmphdr)); - - /* rest is payload */ - offset = *size; - - ip->tot_len = __bswap_16 (offset - sizeof (struct ether_header)); - ip->check = cksum (ip, sizeof (struct iphdr)); - } - } - - assert (offset == *size && "unsupported protocol"); - return 0; -} - - -int -resolve_packet3 (void **pck_, uint32_t * size, uint8_t ip_addr[4]) -{ - struct ether_header *eh; - struct iphdr *ip; - struct icmphdr *icmp; - int32_t offset = 0; - uint16_t encap_size = sizeof (struct ether_header); - void *pck = *pck_; - - if (pck == NULL) - return 0; - - *pck_ -= encap_size; - offset -= encap_size; - - GET_HEADER (eh, struct ether_header, pck, offset); - - uint8_t hw_daddr[6]; - memset (hw_daddr, 0, sizeof (uint8_t) * 6); - - generate_eth (eh, hw_daddr); - - if (eh->ether_type == 0x0008) - { - GET_HEADER (ip, struct iphdr, pck, offset); - - if (ip->protocol == 1) - { - ip->ihl = 5; - ip->version = 4; - ip->tos = 0; - ip->tot_len = 0x0000; - ip->id = 0; - ip->frag_off = 0; - ip->ttl = 0x40; - ip->protocol = 1; - ip->check = 0x0000; - ip->daddr = ip->saddr; - ((uint8_t *) & ip->saddr)[0] = ip_addr[0]; - ((uint8_t *) & ip->saddr)[1] = ip_addr[1]; - ((uint8_t *) & ip->saddr)[2] = ip_addr[2]; - ((uint8_t *) & ip->saddr)[3] = ip_addr[3]; - - GET_HEADER (icmp, struct icmphdr, pck, offset); - - icmp->type = 0x00; - icmp->code = 0; - icmp->checksum = cksum (icmp, sizeof (struct icmphdr)); - - /* rest is payload */ - offset = *size; - - ip->tot_len = __bswap_16 (offset - sizeof (struct ether_header)); - ip->check = cksum (ip, sizeof (struct iphdr)); - } - } - - offset += encap_size; - - assert (offset != *size && - "new packet length must be increased by encap size"); - - /* overwrite packet size */ - *size = offset; - - return 0; -} |