aboutsummaryrefslogtreecommitdiffstats
path: root/icmp.c
diff options
context:
space:
mode:
authorNatanael Copa <ncopa@alpinelinux.org>2013-08-22 14:43:24 +0200
committerNatanael Copa <ncopa@alpinelinux.org>2013-08-22 14:46:10 +0200
commitd3e49c4280f10584587fad83bc08c6a168c174d3 (patch)
tree9127d2f55556a0a049bef296c14da74e0b05904e /icmp.c
parent82ec45bb8abf8052a558e8ad589b66b34a0084fa (diff)
downloadpingu-d3e49c4280f10584587fad83bc08c6a168c174d3.tar.bz2
pingu-d3e49c4280f10584587fad83bc08c6a168c174d3.tar.xz
move soures to src subdir
Diffstat (limited to 'icmp.c')
-rw-r--r--icmp.c359
1 files changed, 0 insertions, 359 deletions
diff --git a/icmp.c b/icmp.c
deleted file mode 100644
index eb1ec5c..0000000
--- a/icmp.c
+++ /dev/null
@@ -1,359 +0,0 @@
-#include <errno.h>
-#include <netdb.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <asm/types.h>
-#include <arpa/inet.h>
-#include <netinet/ip.h>
-#include <netinet/ip_icmp.h>
-
-#include "icmp.h"
-
-static char *pr_addr(__u32 addr)
-{
- struct hostent *hp;
- static char buf[4096];
-
- sprintf(buf, "%s", inet_ntoa(*(struct in_addr *)&addr));
- return buf;
-}
-
-static void pr_icmph(__u8 type, __u8 code, __u32 info, struct icmphdr *icp)
-{
- switch (type) {
- case ICMP_ECHOREPLY:
- printf("Echo Reply\n");
- /* XXX ID + Seq + Data */
- break;
- case ICMP_DEST_UNREACH:
- switch(code) {
- case ICMP_NET_UNREACH:
- printf("Destination Net Unreachable\n");
- break;
- case ICMP_HOST_UNREACH:
- printf("Destination Host Unreachable\n");
- break;
- case ICMP_PROT_UNREACH:
- printf("Destination Protocol Unreachable\n");
- break;
- case ICMP_PORT_UNREACH:
- printf("Destination Port Unreachable\n");
- break;
- case ICMP_FRAG_NEEDED:
- printf("Frag needed and DF set (mtu = %u)\n", info);
- break;
- case ICMP_SR_FAILED:
- printf("Source Route Failed\n");
- break;
- case ICMP_PKT_FILTERED:
- printf("Packet filtered\n");
- break;
- default:
- printf("Dest Unreachable, Bad Code: %d\n", code);
- break;
- }
- break;
- case ICMP_SOURCE_QUENCH:
- printf("Source Quench\n");
- break;
- case ICMP_REDIRECT:
- switch(code) {
- case ICMP_REDIR_NET:
- printf("Redirect Network");
- break;
- case ICMP_REDIR_HOST:
- printf("Redirect Host");
- break;
- case ICMP_REDIR_NETTOS:
- printf("Redirect Type of Service and Network");
- break;
- case ICMP_REDIR_HOSTTOS:
- printf("Redirect Type of Service and Host");
- break;
- default:
- printf("Redirect, Bad Code: %d", code);
- break;
- }
- if (icp)
- printf("(New nexthop: %s)\n", pr_addr(icp->un.gateway));
- break;
- case ICMP_ECHO:
- printf("Echo Request\n");
- /* XXX ID + Seq + Data */
- break;
- case ICMP_TIME_EXCEEDED:
- switch(code) {
- case ICMP_EXC_TTL:
- printf("Time to live exceeded\n");
- break;
- case ICMP_EXC_FRAGTIME:
- printf("Frag reassembly time exceeded\n");
- break;
- default:
- printf("Time exceeded, Bad Code: %d\n", code);
- break;
- }
- break;
- case ICMP_PARAMETERPROB:
- printf("Parameter problem: pointer = %u\n", icp ? (ntohl(icp->un.gateway)>>24) : info);
- break;
- case ICMP_TIMESTAMP:
- printf("Timestamp\n");
- /* XXX ID + Seq + 3 timestamps */
- break;
- case ICMP_TIMESTAMPREPLY:
- printf("Timestamp Reply\n");
- /* XXX ID + Seq + 3 timestamps */
- break;
- case ICMP_INFO_REQUEST:
- printf("Information Request\n");
- /* XXX ID + Seq */
- break;
- case ICMP_INFO_REPLY:
- printf("Information Reply\n");
- /* XXX ID + Seq */
- break;
-#ifdef ICMP_MASKREQ
- case ICMP_MASKREQ:
- printf("Address Mask Request\n");
- break;
-#endif
-#ifdef ICMP_MASKREPLY
- case ICMP_MASKREPLY:
- printf("Address Mask Reply\n");
- break;
-#endif
- default:
- printf("Bad ICMP type: %d\n", type);
- }
-}
-
-static u_short in_cksum(const u_short *addr, register int len, u_short csum)
-{
- const u_short *w = addr;
- u_short answer;
- int sum = csum, nleft = len;
-
- while (nleft > 1) {
- sum += *w++;
- nleft -= 2;
- }
-
- if (nleft == 1)
- sum += htons(*(u_char *)w << 8);
-
- sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
- sum += (sum >> 16); /* add carry */
- answer = ~sum; /* truncate to 16 bits */
-
- return answer;
-}
-
-
-int icmp_parse_reply(__u8 *buf, int len, int seq,
- struct sockaddr *addr,
- struct sockaddr *origdest)
-{
- struct sockaddr_in *from = (struct sockaddr_in *) addr;
- struct sockaddr_in *to = (struct sockaddr_in *) origdest;
- struct icmphdr *icp;
- struct iphdr *ip;
- int hlen, csfailed;
-
- /* Check the IP header */
- ip = (struct iphdr *) buf;
- hlen = ip->ihl * 4;
- if (len < hlen + 8 || ip->ihl < 5)
- return 1;
-
- /* Now the ICMP part */
- len -= hlen;
- icp = (struct icmphdr *)(buf + hlen);
- csfailed = in_cksum((u_short *)icp, len, 0);
-
- if (icp->type == ICMP_ECHOREPLY) {
- if (icp->un.echo.id != getpid() ||
- ntohs(icp->un.echo.sequence) != seq)
- return 1; /* 'Twas not our ECHO */
-
- printf("From %s: icmp_seq=%u bytes=%d\n",
- pr_addr(from->sin_addr.s_addr),
- ntohs(icp->un.echo.sequence), len);
- } else {
- /* We fall here when a redirect or source quench arrived.
- * Also this branch processes icmp errors, when IP_RECVERR
- * is broken. */
-
- switch (icp->type) {
- case ICMP_ECHO:
- /* MUST NOT */
- return 1;
- case ICMP_SOURCE_QUENCH:
- case ICMP_REDIRECT:
- case ICMP_DEST_UNREACH:
- case ICMP_TIME_EXCEEDED:
- case ICMP_PARAMETERPROB:
- {
- struct iphdr * iph = (struct iphdr *)(&icp[1]);
- struct icmphdr *icp1 = (struct icmphdr*)((unsigned char *)iph + iph->ihl*4);
- int error_pkt;
- if (len < 8 + sizeof(struct iphdr) + 8 ||
- len < 8 + iph->ihl * 4 + 8)
- return 1;
- if (icp1->type != ICMP_ECHO ||
- iph->daddr != to->sin_addr.s_addr ||
- icp1->un.echo.id != getpid() ||
- ntohs(icp1->un.echo.sequence) != seq)
- return 1;
- error_pkt = (icp->type != ICMP_REDIRECT &&
- icp->type != ICMP_SOURCE_QUENCH);
- if (error_pkt) {
- //acknowledge(ntohs(icp1->un.echo.sequence));
- }
-
- printf("From %s: icmp_seq=%u ",
- pr_addr(from->sin_addr.s_addr),
- ntohs(icp1->un.echo.sequence));
- if (csfailed)
- printf("(BAD CHECKSUM)");
- pr_icmph(icp->type, icp->code, ntohl(icp->un.gateway), icp);
- return !error_pkt;
- }
- default:
- /* MUST NOT */
- break;
- }
- printf("From %s: ", pr_addr(from->sin_addr.s_addr));
- pr_icmph(icp->type, icp->code, ntohl(icp->un.gateway), icp);
- return 0;
- }
-
- return 0;
-}
-
-int icmp_send(int fd, struct sockaddr *to, int tolen, void *buf, int buflen)
-{
- int i;
-
- i = sendto(fd, buf, buflen, 0, to, tolen);
- if (i != buflen)
- return -1;
-
- return 0;
-}
-
-int icmp_send_frag_needed(int fd, struct sockaddr *to, int tolen,
- struct iphdr *iph, int newmtu)
-{
- struct sockaddr_in *to_in = (struct sockaddr_in *) to;
- const int len = sizeof(struct icmphdr) + sizeof(struct iphdr) + 8;
- char packet[len];
- struct icmphdr *icp;
-
- icp = (struct icmphdr *) packet;
- icp->type = ICMP_DEST_UNREACH;
- icp->code = ICMP_FRAG_NEEDED;
- icp->checksum = 0;
- icp->un.frag.__unused = 0;
- icp->un.frag.mtu = htons(newmtu);
-
- /* copy ip header + 64-bits of original packet */
- memcpy(icp + 1, iph, sizeof(struct iphdr) + 8);
-
- icp->checksum = in_cksum((u_short *) icp, len, 0);
-
- printf("To %s: frag_needed mtu=%d\n",
- pr_addr(to_in->sin_addr.s_addr), newmtu);
-
- return icmp_send(fd, to, tolen, packet, len);
-}
-
-int icmp_send_ping(int fd, struct sockaddr *to, int tolen,
- int seq, int total_size)
-{
- struct sockaddr_in *to_in = (struct sockaddr_in *) to;
- __u8 packet[1500];
- struct icmphdr *icp;
- int len;
-
- if (total_size > sizeof(packet))
- return -1;
- if (total_size < sizeof(struct iphdr) + sizeof(struct icmphdr))
- total_size = sizeof(struct iphdr) + sizeof(struct icmphdr);
-
- len = total_size - sizeof(struct iphdr);
- memset(packet, 0, sizeof(packet));
-
- icp = (struct icmphdr *) packet;
- icp->type = ICMP_ECHO;
- icp->code = 0;
- icp->checksum = 0;
- icp->un.echo.sequence = htons(seq);
- icp->un.echo.id = getpid();
- icp->checksum = in_cksum((u_short *) icp, len, 0);
-#if 0
- printf("To %s: icmp_seq=%u bytes=%d\n",
- pr_addr(to_in->sin_addr.s_addr), seq, len);
-#endif
- return icmp_send(fd, to, tolen, (void *) packet, len);
-}
-
-int icmp_read_reply(int fd, struct sockaddr *from, int fromlen,
- __u8 *buf, int buflen)
-{
- struct iovec iov;
- int len;
-
- len = recvfrom(fd, buf, buflen, 0, from, &fromlen);
- if (len < 0) {
- if (errno == EAGAIN || errno == EINTR)
- return 0;
- return -1;
- }
-
- return len;
-}
-
-int icmp_open(float timeout)
-{
- const int pmtudisc = IP_PMTUDISC_DO, yes = 1;
- struct timeval tv;
- int fd;
-
- fd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
- if (fd < 0) {
- perror("mtuinject: socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)");
- goto err;
- }
-
- if (setsockopt(fd, SOL_IP, IP_MTU_DISCOVER,
- &pmtudisc, sizeof(pmtudisc)) == -1) {
- perror("ping: IP_MTU_DISCOVER");
- goto err_close;
- }
-
- tv.tv_sec = (time_t) timeout;
- tv.tv_usec = (timeout - tv.tv_sec) * 1000000;
- setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char*)&tv, sizeof(tv));
-
- tv.tv_sec = (time_t) timeout;
- tv.tv_usec = (timeout - tv.tv_sec) * 1000000;
- if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO,
- (char*)&tv, sizeof(tv)) == -1)
- goto err_close;
-
- return fd;
-
-err_close:
- close(fd);
-err:
- return -1;
-}
-
-void icmp_close(int fd)
-{
- close(fd);
-}
-