aboutsummaryrefslogtreecommitdiffstats
path: root/network_cmds/ecnprobe/inet.c
diff options
context:
space:
mode:
authorCameron Katri <me@cameronkatri.com>2021-05-09 14:20:58 -0400
committerCameron Katri <me@cameronkatri.com>2021-05-09 14:20:58 -0400
commit5fd83771641d15c418f747bd343ba6738d3875f7 (patch)
tree5abf0f78f680d9837dbd93d4d4c3933bb7509599 /network_cmds/ecnprobe/inet.c
downloadapple_cmds-5fd83771641d15c418f747bd343ba6738d3875f7.tar.gz
apple_cmds-5fd83771641d15c418f747bd343ba6738d3875f7.tar.zst
apple_cmds-5fd83771641d15c418f747bd343ba6738d3875f7.zip
Import macOS userland
adv_cmds-176 basic_cmds-55 bootstrap_cmds-116.100.1 developer_cmds-66 diskdev_cmds-667.40.1 doc_cmds-53.60.1 file_cmds-321.40.3 mail_cmds-35 misc_cmds-34 network_cmds-606.40.1 patch_cmds-17 remote_cmds-63 shell_cmds-216.60.1 system_cmds-880.60.2 text_cmds-106
Diffstat (limited to 'network_cmds/ecnprobe/inet.c')
-rw-r--r--network_cmds/ecnprobe/inet.c503
1 files changed, 503 insertions, 0 deletions
diff --git a/network_cmds/ecnprobe/inet.c b/network_cmds/ecnprobe/inet.c
new file mode 100644
index 0000000..b145412
--- /dev/null
+++ b/network_cmds/ecnprobe/inet.c
@@ -0,0 +1,503 @@
+/*
+ Copyright (c) 2000
+ International Computer Science Institute
+ All rights reserved.
+
+ This file may contain software code originally developed for the
+ Sting project. The Sting software carries the following copyright:
+
+ Copyright (c) 1998, 1999
+ Stefan Savage and the University of Washington.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. All advertising materials mentioning features or use of this software
+ must display the following acknowledgment:
+ This product includes software developed by ACIRI, the AT&T
+ Center for Internet Research at ICSI (the International Computer
+ Science Institute). This product may also include software developed
+ by Stefan Savage at the University of Washington.
+ 4. The names of ACIRI, ICSI, Stefan Savage and University of Washington
+ may not be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY ICSI AND CONTRIBUTORS ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL ICSI OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
+*/
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include "base.h"
+#include "inet.h"
+#include "session.h"
+#include "capture.h"
+#include "support.h"
+#include "history.h"
+
+extern struct TcpSession session;
+extern struct History history[];
+
+/*
+ * Deal with struct in_addr type agreement once and for all
+ */
+char *InetAddress(uint32 addr)
+{
+
+ struct in_addr s;
+ s.s_addr = addr;
+
+ //printf("In InetAddress:\n");
+ //printf("addr = %s (%0x)\n", inet_ntoa(s), addr);
+
+ return (inet_ntoa(s));
+}
+
+/*
+ * Really slow implementation of ip checksum
+ * ripped off from rfc1071
+ */
+
+uint16 InetChecksum(uint16 *ip, uint16 *tcp, uint16 ip_len, uint16 tcp_len) {
+
+ uint32 sum = 0;
+
+ uint32 ip_count = ip_len;
+ uint32 tcp_count = tcp_len;
+ uint16 *ip_addr = ip;
+ uint16 *tcp_addr = tcp;
+
+ if (session.debug >= SESSION_DEBUG_HIGH) {
+ printf("In InetChecksum...\n");
+ printf("iplen: %d, tcplen: %d\n", ip_len, tcp_len);
+ }
+
+
+ while(ip_count > 1) {
+ //printf("ip[%d]: %x\n", ip_len - ip_count, htons(*ip_addr));
+ sum += *ip_addr++;
+ ip_count -= 2;
+ }
+
+ while(tcp_count > 1) {
+ //printf("tcp[%d]: %x\n", tcp_len - tcp_count, htons(*tcp_addr));
+ sum += *tcp_addr++;
+ tcp_count -= 2;
+ }
+
+ if(ip_count > 0) {
+ sum += *(uint8 *)ip_addr;
+ }
+
+ if(tcp_count > 0) {
+ sum += *(uint8 *)tcp_addr;
+ }
+
+ while (sum >> 16) {
+ sum = (sum & 0xffff) + (sum >> 16);
+ }
+
+ if (session.debug >= SESSION_DEBUG_HIGH) {
+ printf("Out InetChecksum...\n");
+ }
+
+ return(~sum);
+
+}
+
+
+void WriteIPPacket(struct IPPacket *p,
+ uint32 src,
+ uint32 dst,
+ uint16 sport,
+ uint16 dport,
+ uint32 seq,
+ uint32 ack,
+ uint8 flags,
+ uint16 win,
+ uint16 urp,
+ uint16 datalen,
+ uint16 ip_optlen,
+ uint16 optlen,
+ uint8 iptos,
+ uint8 u4tf)
+{
+
+ struct IpHeader *ip = p->ip;
+ struct TcpHeader *tcp = p->tcp;
+
+ if (session.debug >= SESSION_DEBUG_HIGH) {
+ printf("In WriteIPPacket...\n");
+ }
+
+ /* Zero out IpHeader to ensure proper checksum computation */
+ bzero((char *)(p->ip), sizeof(struct IpHeader));
+
+ ip->ip_src = src;
+ ip->ip_dst = dst;
+ ip->ip_p = IPPROTOCOL_TCP;
+ ip->ip_xsum =
+ htons((uint16)(sizeof(struct TcpHeader) + datalen + optlen)); /* pseudo hdr */
+
+ tcp->tcp_sport = htons(sport);
+ tcp->tcp_dport = htons(dport);
+ tcp->tcp_seq = htonl(seq);
+ tcp->tcp_ack = htonl(ack);
+ tcp->tcp_hl = (sizeof(struct TcpHeader) + optlen) << 2;
+ tcp->tcp_hl = tcp->tcp_hl | u4tf;
+ tcp->tcp_flags = flags;
+
+ tcp->tcp_win = htons(win);
+ tcp->tcp_urp = htons(urp);
+
+ tcp->tcp_xsum = 0;
+ tcp->tcp_xsum = InetChecksum((uint16 *)ip, (uint16 *)tcp,
+ (uint16)sizeof(struct IpHeader), /* IP Options should aren't included */
+ (uint16)(sizeof(struct TcpHeader) + datalen + optlen));
+
+ /* Fill in real ip header */
+ if (session.curr_ttl != 0) {
+ ip->ip_ttl = session.curr_ttl;
+ }else {
+ ip->ip_ttl = 60;
+ }
+
+ //printf("TTL: %d\n", ip->ip_ttl);
+
+ ip->ip_tos = iptos;
+
+ /* IP Version and Header len field */
+ ip->ip_vhl = 0x40 + 0x5 + (int)(ip_optlen/4);
+ ip->ip_p = IPPROTOCOL_TCP;
+
+ ip->ip_off = IP_DF;
+ ip->ip_len = (uint16)(sizeof(struct IpHeader) + ip_optlen + sizeof(struct TcpHeader) + optlen + datalen);
+
+ ip->ip_xsum = 0;
+ ip->ip_xsum = InetChecksum((uint16 *)ip, NULL,
+ (uint16)sizeof(struct IpHeader) + ip_optlen, /* IP Options should aren't included */
+ 0);
+
+ if (session.debug >= SESSION_DEBUG_HIGH) {
+ printf("Out WriteIPPacket...\n");
+ }
+
+}
+
+void ReadIPPacket(struct IPPacket *p,
+ uint32 *src,
+ uint32 *dst,
+ uint16 *sport,
+ uint16 *dport,
+ uint32 *seq,
+ uint32 *ack,
+ uint8 *flags,
+ uint16 *win,
+ uint16 *urp,
+ uint16 *datalen,
+ uint16 *ip_optlen,
+ uint16 *optlen)
+{
+
+ /* TODO: Add reading of IP options, if any */
+
+ struct IpHeader *ip = p->ip;
+ struct TcpHeader *tcp = p->tcp;
+
+ uint16 ip_len;
+ uint16 ip_hl;
+ uint16 tcp_hl;
+
+ /* XXX do checksum check? */
+ if (ip->ip_p != IPPROTOCOL_TCP && ip->ip_p != IPPROTOCOL_ICMP) {
+ printf("Unexpected protocol packet: %u\n", ip->ip_p);
+ Quit(ERR_CHECKSUM);
+ }
+
+ *src = ip->ip_src;
+ *dst = ip->ip_dst;
+ *sport = ntohs(tcp->tcp_sport);
+ *dport = ntohs(tcp->tcp_dport);
+ *seq = ntohl(tcp->tcp_seq);
+ *ack = ntohl(tcp->tcp_ack);
+ *flags = tcp->tcp_flags;
+ *win = ntohs(tcp->tcp_win);
+ *urp = ntohs(tcp->tcp_urp);
+
+ tcp_hl = tcp->tcp_hl >> 2;
+ ip_len = ntohs(ip->ip_len);
+ ip_hl = (ip->ip_vhl & 0x0f) << 2;
+ *datalen = (ip_len - ip_hl) - tcp_hl;
+ *ip_optlen = ip_hl - (unsigned int)sizeof(struct IpHeader); /* added to support IP Options */
+ *optlen = tcp_hl - (unsigned int)sizeof(struct TcpHeader);
+
+}
+
+void PrintICMPUnreachableErrorPacket(struct ICMPUnreachableErrorPacket *p)
+{
+
+ struct IpHeader *ip = &p->ip;
+ struct IcmpHeader *icmp = &p->icmp;
+ struct IpHeader *off_ip = &p->off_ip;
+
+ printf("IPHdr: ");
+ printf("%s > ", InetAddress(ip->ip_src));
+ printf("%s ", InetAddress(ip->ip_dst));
+ printf(" datalen: %u\n", ip->ip_len);
+ printf("ICMPHdr: ");
+ printf("Type: %u Code: %u MTU next hop: %u xsum: %x\n",
+ icmp->icmp_type,
+ icmp->icmp_code,
+ ntohs(icmp->icmp_mtu),
+ icmp->icmp_xsum);
+ printf("Off IPHdr: ");
+ printf("%s > ", InetAddress(off_ip->ip_src));
+ printf("%s ", InetAddress(off_ip->ip_dst));
+ printf(" datalen: %u ", off_ip->ip_len);
+ printf("tcp sport: %u ", ntohs(p->tcp_sport));
+ printf("tcp dport: %u ", ntohs(p->tcp_dport));
+ printf("tcp seqno: %u\n", (uint32)ntohl(p->tcp_seqno));
+
+}
+
+void PrintTcpPacket(struct IPPacket *p)
+{
+
+ struct IpHeader *ip = p->ip;
+ struct TcpHeader *tcp = p->tcp;
+
+ char *opt;
+ int optlen;
+ char *ip_opt;
+ int ip_optlen;
+ int i;
+
+ printf("%s.%u > ", InetAddress(ip->ip_src), ntohs(tcp->tcp_sport));
+ printf("%s.%u ", InetAddress(ip->ip_dst), ntohs(tcp->tcp_dport));
+
+ if (tcp->tcp_flags & TCPFLAGS_SYN) {
+ printf("S");
+ }
+
+ if (tcp->tcp_flags & TCPFLAGS_ACK) {
+ printf("A");
+ }
+
+ if (tcp->tcp_flags & TCPFLAGS_FIN) {
+ printf("F");
+ }
+
+ if (tcp->tcp_flags & TCPFLAGS_ECN_ECHO) {
+ printf("E");
+ }
+
+ if (tcp->tcp_flags & TCPFLAGS_CWR) {
+ printf("W");
+ }
+
+ if (tcp->tcp_flags & TCPFLAGS_RST) {
+ printf("R");
+ }
+ if (tcp->tcp_flags & TCPFLAGS_PSH) {
+ printf("P");
+ }
+
+ if (tcp->tcp_flags & TCPFLAGS_URG) {
+ printf("U");
+ }
+
+ if (INSESSION(p,session.src,session.sport,session.dst,session.dport)) {
+ printf(" seq: %u, ack: %u", (uint32)ntohl(tcp->tcp_seq) - session.iss, (uint32)ntohl(tcp->tcp_ack) - session.irs);
+ } else {
+ printf(" seq: %u, ack: %u", (uint32)ntohl(tcp->tcp_seq) - session.irs, (uint32)ntohl(tcp->tcp_ack) - session.iss);
+ }
+
+ /* IP Options */
+ ip_optlen = ((ip->ip_vhl & 0x0f) << 2) - sizeof(struct IpHeader);
+ ip_opt = (char *)ip + sizeof(struct IpHeader);
+
+ i = 0;
+ while (i < ip_optlen) {
+
+ switch ((unsigned char)ip_opt[i]) {
+ case IPOPT_NOP:
+ printf(" ipopt%d: %s ", i + 1, "IPOPT_NOP");
+ i = i + 1;
+ break;
+
+ case IPOPT_EOL:
+ printf(" ipopt%d: %s ", i + 1, "IPOPT_EOL");
+ i = ip_optlen + 1;
+ break;
+
+ case IPOPT_RR:
+ printf(" ipopt%d: %s ", i + 1, "IPOPT_RR");
+ i = i + IPOLEN_RR;
+ break;
+
+ default:
+ printf("ip_opt%d: UNKNOWN ", i + 1);
+ i = i + (uint8)ip_opt[i+1] ;
+ }
+ }
+
+ printf(" win: %u, urg: %u, ttl: %d", ntohs(tcp->tcp_win), ntohs(tcp->tcp_urp), ip->ip_ttl);
+ printf(" datalen: %u, optlen: %u ",
+ ip->ip_len - ((ip->ip_vhl &0x0f) << 2) - (tcp->tcp_hl >> 2),
+ (tcp->tcp_hl >> 2) - (unsigned int)sizeof(struct TcpHeader));
+
+
+ /* TCP Options */
+ optlen = (tcp->tcp_hl >> 2) - (unsigned int)sizeof (struct TcpHeader) ;
+ opt = (char *)tcp + sizeof(struct TcpHeader);
+
+ i = 0 ;
+
+ while (i < optlen) {
+
+ switch ((unsigned char)opt[i]) {
+
+ case TCPOPT_EOL:
+ printf (" opt%d: %s ", i + 1, "TCPOPT_EOL");
+ i = optlen + 1;
+ break ;
+
+ case TCPOPT_NOP:
+ printf (" opt%d: %s ", i + 1, "TCPOPT_NOP");
+ i++ ;
+ break ;
+
+ case TCPOPT_MAXSEG:
+ printf (" opt%d: %s: %d ", i + 1, "TCPOPT_MAXSEG", ntohs(*(uint16 *)((char *)opt+2)));
+ i = i + TCPOLEN_MAXSEG ;
+ break ;
+
+ case TCPOPT_WINDOW:
+ printf (" opt%d: %s ", i + 1, "TCPOPT_WINDOW");
+ i = i + TCPOLEN_WINDOW ;
+ break ;
+
+ case TCPOPT_SACK_PERMITTED:
+ printf (" opt%d: %s ", i + 1, "TCPOPT_SACK_PERMITTED");
+ i = i + TCPOLEN_SACK_PERMITTED ;
+ break ;
+
+ case TCPOPT_TIMESTAMP:
+ printf (" opt%d: %s ", i + 1, "TCPOPT_TIMESTAMP");
+ i = i + TCPOLEN_TIMESTAMP ;
+ break ;
+
+ default:
+ printf (" opt%d c:%d l:%d: UNKNOWN ", i + 1, (uint8)opt[i], (uint8)opt[i+1]);
+ if ((uint8)opt[i+1] > 0) {
+ i = i + (uint8)opt[i+1] ;
+ } else {
+ Quit(20);
+ }
+ break ;
+ }
+ }
+ printf ("\n");
+}
+
+
+struct IPPacket *FindHeaderBoundaries(char *p) {
+
+ struct IPPacket *packet;
+ uint16 ip_hl;
+
+ if ((packet = (struct IPPacket *)calloc(1, sizeof(struct IPPacket))) == NULL) {
+ printf("FindHeaderBoundaries: Cannot allocate memory for read packet\nRETURN CODE: %d\n", ERR_MEM_ALLOC);
+ Quit(ERR_MEM_ALLOC);
+ }
+
+ packet->ip = (struct IpHeader *)p;
+
+ if (packet->ip->ip_p != IPPROTOCOL_TCP &&
+ packet->ip->ip_p != IPPROTOCOL_ICMP) {
+ printf("Error: Unexpected protocol packet: %u \n", packet->ip->ip_p);
+ Quit(ERR_CHECKSUM);
+ }
+
+ ip_hl = (packet->ip->ip_vhl & 0x0f) << 2;
+
+ packet->tcp = (struct TcpHeader *)((char *)p + ip_hl);
+ return packet;
+
+}
+
+
+struct IPPacket *
+AllocateIPPacket(int ip_optlen, int tcp_optlen, int datalen, char *str)
+{
+ struct IPPacket *p;
+
+ if (session.debug >= SESSION_DEBUG_HIGH) {
+ printf("In AllocateIPPacket: %s...\n", str);
+ }
+
+ if ((p = (struct IPPacket *)calloc(1, sizeof(struct IPPacket)))
+ == NULL) {
+ printf("%s ERROR: No space for packet\nRETURN CODE: %d",
+ str, ERR_MEM_ALLOC);
+ Quit(ERR_MEM_ALLOC);
+ }
+
+ if ((p->ip = (struct IpHeader *)calloc(1,
+ sizeof(struct IpHeader) + ip_optlen)) == NULL) {
+ printf("%s ERROR: No IpHeader space for packet\n"
+ "RETURN CODE: %d", str, ERR_MEM_ALLOC);
+ Quit(ERR_MEM_ALLOC);
+ }
+
+ if ((p->tcp = (struct TcpHeader *)calloc(1,
+ sizeof(struct TcpHeader) + tcp_optlen + datalen)) == NULL) {
+ printf("%s ERROR: No TcpHeader space for packet\n"
+ "RETURN CODE: %d", str, ERR_MEM_ALLOC);
+ Quit(ERR_MEM_ALLOC);
+ }
+
+ if (session.debug >= SESSION_DEBUG_HIGH) {
+ printf("Out of AllocateIPPacket: %s...\n", str);
+ }
+ return(p);
+}
+
+void
+FreeIPPacket(struct IPPacket **pkt_p)
+{
+ struct IPPacket *pkt;
+ if (pkt_p == NULL)
+ return;
+ if ((pkt = *pkt_p) == NULL)
+ return;
+ if (pkt->ip != NULL) {
+ free(pkt->ip);
+ pkt->ip = NULL;
+ }
+ if (pkt->tcp != NULL) {
+ free(pkt->tcp);
+ pkt->tcp = NULL;
+ }
+ free(pkt);
+ *pkt_p = NULL;
+}
+