mirror of
https://github.com/rcornwell/sims.git
synced 2026-02-05 07:55:12 +00:00
KA10: Fix IMP ICMP and add detailed debug options
- ICMP Echo and Echo reply packets mangled the ICMP checksum when no mangling was needed. - Other ICMP message types may still be wrong since they potentially contain IP header information that may or may not need IP addresses manipulated - Increased the ARP table size from 8 to 64 since the ARP RFC (826) suggests that ARP info from all received ARP packets be gathered as ARP broadcasts are received. A normal LAN can easily blow over an 8 entry ARP table.
This commit is contained in:
383
PDP10/kx10_imp.c
383
PDP10/kx10_imp.c
@@ -145,7 +145,7 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define IMP_ARPTAB_SIZE 8
|
||||
#define IMP_ARPTAB_SIZE 64
|
||||
#define IMP_ARP_MAX_AGE 100
|
||||
|
||||
uint32 mask[] = {
|
||||
@@ -199,6 +199,12 @@ struct tcp {
|
||||
uint32 seq; /* Sequence number */
|
||||
uint32 ack; /* Ack number */
|
||||
uint16 flags; /* Flags */
|
||||
#define TCP_FL_FIN 0x01
|
||||
#define TCP_FL_SYN 0x02
|
||||
#define TCP_FL_RST 0x04
|
||||
#define TCP_FL_PSH 0x08
|
||||
#define TCP_FL_ACK 0x10
|
||||
#define TCP_FL_URG 0x20
|
||||
uint16 window; /* Window size */
|
||||
uint16 chksum; /* packet checksum */
|
||||
uint16 urgent; /* Urgent pointer */
|
||||
@@ -473,6 +479,8 @@ void imp_arp_arpin(struct imp_device *imp, ETH_PACK *packet);
|
||||
void imp_arp_arpout(struct imp_device *imp, in_addr_T ipaddr);
|
||||
struct arp_entry * imp_arp_lookup(struct imp_device *imp, in_addr_T ipaddr);
|
||||
void imp_packet_out(struct imp_device *imp, ETH_PACK *packet);
|
||||
void imp_packet_debug(struct imp_device *imp, const char *action, ETH_PACK *packet);
|
||||
void imp_write(struct imp_device *imp, ETH_PACK *packet);
|
||||
void imp_do_dhcp_client(struct imp_device *imp, ETH_PACK *packet);
|
||||
void imp_dhcp_timer(struct imp_device *imp);
|
||||
void imp_dhcp_discover(struct imp_device *imp);
|
||||
@@ -529,11 +537,38 @@ MTAB imp_mod[] = {
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
/* Simulator debug controls */
|
||||
DEBTAB imp_debug[] = {
|
||||
{"CMD", DEBUG_CMD, "Show command execution to devices"},
|
||||
{"DATA", DEBUG_DATA, "Show data transfers"},
|
||||
{"DETAIL", DEBUG_DETAIL, "Show details about device"},
|
||||
{"EXP", DEBUG_EXP, "Show exception information"},
|
||||
{"CONI", DEBUG_CONI, "Show coni instructions"},
|
||||
{"CONO", DEBUG_CONO, "Show coni instructions"},
|
||||
{"DATAIO", DEBUG_DATAIO, "Show datai and datao instructions"},
|
||||
{"IRQ", DEBUG_IRQ, "Show IRQ requests"},
|
||||
#define DEBUG_DHCP (DEBUG_IRQ<<1)
|
||||
{"DHCP", DEBUG_DHCP, "Show DHCP activities"},
|
||||
#define DEBUG_ARP (DEBUG_DHCP<<1)
|
||||
{"ARP", DEBUG_ARP, "Show ARP activities"},
|
||||
#define DEBUG_TCP (DEBUG_ARP<<1)
|
||||
{"TCP", DEBUG_TCP, "Show TCP packet activities"},
|
||||
#define DEBUG_UDP (DEBUG_TCP<<1)
|
||||
{"UDP", DEBUG_UDP, "Show UDP packet activities"},
|
||||
#define DEBUG_ICMP (DEBUG_UDP<<1)
|
||||
{"ICMP", DEBUG_ICMP, "Show ICMP packet activities"},
|
||||
#define DEBUG_ETHER (DEBUG_ICMP<<1)
|
||||
{"ETHER", DEBUG_ETHER, "Show ETHER activities"},
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
|
||||
|
||||
DEVICE imp_dev = {
|
||||
"IMP", imp_unit, NULL, imp_mod,
|
||||
3, 8, 0, 1, 8, 36,
|
||||
NULL, NULL, &imp_reset, NULL, &imp_attach, &imp_detach,
|
||||
&imp_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG, 0, dev_debug,
|
||||
&imp_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG, 0, imp_debug,
|
||||
NULL, NULL, &imp_help, NULL, NULL, &imp_description
|
||||
};
|
||||
#define IMP_OCHN 0000007
|
||||
@@ -831,8 +866,8 @@ t_stat imp_eth_srv(UNIT * uptr)
|
||||
imp_data.dhcp_state != DHCP_STATE_REBINDING &&
|
||||
imp_data.dhcp_state != DHCP_STATE_RENEWING)
|
||||
return SCPE_OK;
|
||||
sim_debug(DEBUG_DETAIL, &imp_dev, "IMP init Nop %d\n",
|
||||
imp_data.init_state);
|
||||
sim_debug(DEBUG_DETAIL, &imp_dev, "IMP init Nop %d\n",
|
||||
imp_data.init_state);
|
||||
if (imp_unit[0].ILEN == 0) {
|
||||
/* Queue up a nop packet */
|
||||
imp_data.rbuffer[0] = 0x4;
|
||||
@@ -922,6 +957,7 @@ imp_packet_in(struct imp_device *imp)
|
||||
}
|
||||
return;
|
||||
}
|
||||
imp_packet_debug(imp, "Received", &read_buffer);
|
||||
hdr = (struct imp_eth_hdr *)(&read_buffer.msg[0]);
|
||||
type = ntohs(hdr->type);
|
||||
if (type == ETHTYPE_ARP) {
|
||||
@@ -1083,9 +1119,11 @@ imp_packet_in(struct imp_device *imp)
|
||||
/* Lastly check if ICMP */
|
||||
} else if (ip_hdr->ip_p == ICMP_PROTO) {
|
||||
struct icmp *icmp_hdr = (struct icmp *)payload;
|
||||
checksumadjust((uint8 *)&icmp_hdr->chksum,
|
||||
(uint8 *)(&ip_hdr->ip_src), sizeof(in_addr_T),
|
||||
(uint8 *)(&imp_data.hostip), sizeof(in_addr_T));
|
||||
if ((icmp_hdr->type != 0) && /* Not Echo Reply */
|
||||
(icmp_hdr->type != 8)) /* and Not Echo */
|
||||
checksumadjust((uint8 *)&icmp_hdr->chksum,
|
||||
(uint8 *)(&ip_hdr->ip_src), sizeof(in_addr_T),
|
||||
(uint8 *)(&imp_data.hostip), sizeof(in_addr_T));
|
||||
}
|
||||
checksumadjust((uint8 *)&ip_hdr->ip_sum,
|
||||
(uint8 *)(&ip_hdr->ip_dst), sizeof(in_addr_T),
|
||||
@@ -1309,9 +1347,11 @@ imp_packet_out(struct imp_device *imp, ETH_PACK *packet) {
|
||||
/* Lastly check if ICMP */
|
||||
} else if (pkt->iphdr.ip_p == ICMP_PROTO) {
|
||||
struct icmp *icmp_hdr = (struct icmp *)payload;
|
||||
checksumadjust((uint8 *)&icmp_hdr->chksum,
|
||||
(uint8 *)(&pkt->iphdr.ip_src), sizeof(in_addr_T),
|
||||
(uint8 *)(&imp->ip), sizeof(in_addr_T));
|
||||
if ((icmp_hdr->type != 0) && /* Not Echo Reply */
|
||||
(icmp_hdr->type != 8)) /* and Not Echo */
|
||||
checksumadjust((uint8 *)&icmp_hdr->chksum,
|
||||
(uint8 *)(&pkt->iphdr.ip_src), sizeof(in_addr_T),
|
||||
(uint8 *)(&imp->ip), sizeof(in_addr_T));
|
||||
}
|
||||
/* Lastly update the header and IP address */
|
||||
checksumadjust((uint8 *)&pkt->iphdr.ip_sum,
|
||||
@@ -1337,7 +1377,7 @@ imp_packet_out(struct imp_device *imp, ETH_PACK *packet) {
|
||||
memcpy(&pkt->ethhdr.dest, &tabptr->ethaddr, 6);
|
||||
memcpy(&pkt->ethhdr.src, &imp->mac, 6);
|
||||
pkt->ethhdr.type = htons(ETHTYPE_IP);
|
||||
eth_write(&imp->etherface, packet, NULL);
|
||||
imp_write(imp, packet);
|
||||
imp->rfnm_count++;
|
||||
return;
|
||||
}
|
||||
@@ -1357,6 +1397,259 @@ imp_packet_out(struct imp_device *imp, ETH_PACK *packet) {
|
||||
}
|
||||
|
||||
|
||||
void imp_packet_debug(struct imp_device *imp, const char *action, ETH_PACK *packet) {
|
||||
struct imp_eth_hdr *eth = (struct imp_eth_hdr *)&packet->msg[0];
|
||||
struct arp_hdr *arp = (struct arp_hdr *)eth;
|
||||
struct ip *ip = (struct ip *)&packet->msg[sizeof(struct imp_eth_hdr)];
|
||||
struct udp *udp;
|
||||
struct tcp *tcp;
|
||||
struct icmp *icmp;
|
||||
uint8 *payload;
|
||||
struct in_addr ipaddr;
|
||||
size_t len;
|
||||
int flag;
|
||||
char src_ip[20];
|
||||
char dst_ip[20];
|
||||
char src_port[8];
|
||||
char dst_port[8];
|
||||
char mac_buf[20];
|
||||
char flags[64];
|
||||
static struct tcp_flag_bits {
|
||||
const char *name;
|
||||
uint16 bitmask;
|
||||
} bits[] = {
|
||||
{"FIN", TCP_FL_FIN},
|
||||
{"SYN", TCP_FL_SYN},
|
||||
{"RST", TCP_FL_RST},
|
||||
{"PSH", TCP_FL_PSH},
|
||||
{"ACK", TCP_FL_ACK},
|
||||
{"URG", TCP_FL_URG},
|
||||
{NULL, 0}
|
||||
};
|
||||
static const char *icmp_types[] = {
|
||||
"Echo Reply", // Type 0
|
||||
"Type 1 - Unassigned",
|
||||
"Type 2 - Unassigned",
|
||||
"Destination Unreachable", // Type 3
|
||||
"Source Quench (Deprecated)", // Type 4
|
||||
"Redirect", // Type 5
|
||||
"Type 6 - Alternate Host Address (Deprecated)",
|
||||
"Type 7 - Unassigned",
|
||||
"Echo Request", // Type 8
|
||||
"Router Advertisement", // Type 9
|
||||
"Router Selection", // Type 10
|
||||
"Time Exceeded", // Type 11
|
||||
"Type 12 - Parameter Problem",
|
||||
"Type 13 - Timestamp",
|
||||
"Type 14 - Timestamp Reply",
|
||||
"Type 15 - Information Request (Deprecated)",
|
||||
"Type 16 - Information Reply (Deprecated)",
|
||||
"Type 17 - Address Mask Request (Deprecated)",
|
||||
"Type 18 - Address Mask Reply (Deprecated)",
|
||||
"Type 19 - Reserved (for Security)",
|
||||
"Type 20 - Reserved (for Robustness Experiment)",
|
||||
"Type 21 - Reserved (for Robustness Experiment)",
|
||||
"Type 22 - Reserved (for Robustness Experiment)",
|
||||
"Type 23 - Reserved (for Robustness Experiment)",
|
||||
"Type 24 - Reserved (for Robustness Experiment)",
|
||||
"Type 25 - Reserved (for Robustness Experiment)",
|
||||
"Type 26 - Reserved (for Robustness Experiment)",
|
||||
"Type 27 - Reserved (for Robustness Experiment)",
|
||||
"Type 28 - Reserved (for Robustness Experiment)",
|
||||
"Type 29 - Reserved (for Robustness Experiment)",
|
||||
"Type 30 - Traceroute (Deprecated)",
|
||||
"Type 31 - Datagram Conversion Error (Deprecated)",
|
||||
"Type 32 - Mobile Host Redirect (Deprecated)",
|
||||
"Type 33 - IPv6 Where-Are-You (Deprecated)",
|
||||
"Type 34 - IPv6 I-Am-Here (Deprecated)",
|
||||
"Type 35 - Mobile Registration Request (Deprecated)",
|
||||
"Type 36 - Mobile Registration Reply (Deprecated)",
|
||||
"Type 37 - Domain Name Request (Deprecated)",
|
||||
"Type 38 - Domain Name Reply (Deprecated)",
|
||||
"Type 39 - SKIP (Deprecated)",
|
||||
"Type 40 - Photuris",
|
||||
"Type 41 - ICMP messages utilized by experimental mobility protocols such as Seamoby",
|
||||
"Type 42 - Extended Echo Request",
|
||||
"Type 43 - Extended Echo Reply"
|
||||
};
|
||||
|
||||
if (ntohs(eth->type) == ETHTYPE_ARP) {
|
||||
struct in_addr in_addr;
|
||||
const char *arp_op = (ARP_REQUEST == ntohs(arp->opcode)) ? "REQUEST" : ((ARP_REPLY == ntohs(arp->opcode)) ? "REPLY" : "Unknown");
|
||||
char eth_src[20], eth_dst[20];
|
||||
char arp_shwaddr[20], arp_dhwaddr[20];
|
||||
char arp_sipaddr[20], arp_dipaddr[20];
|
||||
|
||||
if (!(imp_dev.dctrl & DEBUG_ARP))
|
||||
return;
|
||||
eth_mac_fmt(&arp->ethhdr.src, eth_src);
|
||||
eth_mac_fmt(&arp->ethhdr.dest, eth_dst);
|
||||
eth_mac_fmt(&arp->shwaddr, arp_shwaddr);
|
||||
memcpy(&in_addr, &arp->sipaddr, sizeof(in_addr));
|
||||
strlcpy(arp_sipaddr, ipv4_inet_ntoa(in_addr), sizeof(arp_sipaddr));
|
||||
eth_mac_fmt(&arp->dhwaddr, arp_dhwaddr);
|
||||
memcpy(&in_addr, &arp->dipaddr, sizeof(in_addr));
|
||||
strlcpy(arp_dipaddr, ipv4_inet_ntoa(in_addr), sizeof(arp_dipaddr));
|
||||
sim_debug(DEBUG_ARP, &imp_dev,
|
||||
"%s %s EthDst=%s EthSrc=%s shwaddr=%s sipaddr=%s dhwaddr=%s dipaddr=%s\n",
|
||||
action, arp_op, eth_dst, eth_src, arp_shwaddr, arp_sipaddr, arp_dhwaddr, arp_dipaddr);
|
||||
return;
|
||||
}
|
||||
if (ntohs(eth->type) != ETHTYPE_IP)
|
||||
return;
|
||||
if (!(imp_dev.dctrl & (DEBUG_TCP|DEBUG_UDP|DEBUG_ICMP)))
|
||||
return;
|
||||
memcpy(&ipaddr, &ip->ip_src, sizeof(ipaddr));
|
||||
strlcpy(src_ip, ipv4_inet_ntoa(ipaddr), sizeof(src_ip));
|
||||
memcpy(&ipaddr, &ip->ip_dst, sizeof(ipaddr));
|
||||
strlcpy(dst_ip, ipv4_inet_ntoa(ipaddr), sizeof(dst_ip));
|
||||
payload = (uint8 *)&packet->msg[sizeof(struct imp_eth_hdr) + (ip->ip_v_hl & 0xf) * 4];
|
||||
switch (ip->ip_p) {
|
||||
case UDP_PROTO:
|
||||
udp = (struct udp *)payload;
|
||||
snprintf(src_port, sizeof(src_port), "%d", ntohs(udp->udp_sport));
|
||||
snprintf(dst_port, sizeof(dst_port), "%d", ntohs(udp->udp_dport));
|
||||
sim_debug(DEBUG_UDP, &imp_dev, "%s %d byte packet from %s:%s to %s:%s\n", action,
|
||||
ntohs(udp->len), src_ip, src_port, dst_ip, dst_port);
|
||||
if ((imp_dev.dctrl & DEBUG_DHCP) &&
|
||||
(((ntohs(udp->udp_sport) == DHCP_UDP_PORT_CLIENT) &&
|
||||
(ntohs(udp->udp_dport) == DHCP_UDP_PORT_SERVER)) ||
|
||||
((ntohs(udp->udp_dport) == DHCP_UDP_PORT_CLIENT) &&
|
||||
(ntohs(udp->udp_sport) == DHCP_UDP_PORT_SERVER)))) {
|
||||
struct dhcp *dhcp = (struct dhcp *)(payload + sizeof(struct udp));
|
||||
uint8 *opt = &dhcp->options[0];
|
||||
|
||||
sim_debug(DEBUG_DHCP, &imp_dev, "%s XID=%08X",
|
||||
(dhcp->op == DHCP_BOOTREQUEST) ? "REQUEST" :
|
||||
(dhcp->op == DHCP_BOOTREPLY) ? "REPLY" :
|
||||
"??????",
|
||||
dhcp->xid);
|
||||
if (dhcp->ciaddr) {
|
||||
memcpy(&ipaddr, &dhcp->ciaddr, sizeof(ipaddr));
|
||||
sim_debug(DEBUG_DHCP, &imp_dev, ", ciaddr=%s", ipv4_inet_ntoa(ipaddr));
|
||||
}
|
||||
if (dhcp->yiaddr) {
|
||||
memcpy(&ipaddr, &dhcp->yiaddr, sizeof(ipaddr));
|
||||
sim_debug(DEBUG_DHCP, &imp_dev, ", yiaddr=%s", ipv4_inet_ntoa(ipaddr));
|
||||
}
|
||||
if (dhcp->siaddr) {
|
||||
memcpy(&ipaddr, &dhcp->siaddr, sizeof(ipaddr));
|
||||
sim_debug(DEBUG_DHCP, &imp_dev, ", siaddr=%s", ipv4_inet_ntoa(ipaddr));
|
||||
}
|
||||
if (dhcp->giaddr) {
|
||||
memcpy(&ipaddr, &dhcp->giaddr, sizeof(ipaddr));
|
||||
sim_debug(DEBUG_DHCP, &imp_dev, ", giaddr=%s", ipv4_inet_ntoa(ipaddr));
|
||||
}
|
||||
eth_mac_fmt((ETH_MAC*)&dhcp->chaddr, mac_buf);
|
||||
sim_debug(DEBUG_DHCP, &imp_dev, ", chaddr=%s Options: ", mac_buf);
|
||||
while (*opt != DHCP_OPTION_END) {
|
||||
int opt_len;
|
||||
u_long numeric;
|
||||
static const char *opr_names[] = {
|
||||
"", "DISCOVER", "OFFER", "REQUEST",
|
||||
"DECLINE", "ACK", "NAK", "RELEASE",
|
||||
"INFORM"
|
||||
};
|
||||
|
||||
|
||||
switch(*opt++) {
|
||||
case DHCP_OPTION_PAD:
|
||||
break;
|
||||
default:
|
||||
opt_len = *opt++;
|
||||
opt += opt_len;
|
||||
break;
|
||||
case DHCP_OPTION_SUBNET_MASK:
|
||||
opt_len = *opt++;
|
||||
memcpy(&ipaddr, opt, 4);
|
||||
sim_debug(DEBUG_DHCP, &imp_dev, ", mask=%s", ipv4_inet_ntoa(ipaddr));
|
||||
opt += opt_len;
|
||||
break;
|
||||
case DHCP_OPTION_ROUTER:
|
||||
opt_len = *opt++;
|
||||
memcpy(&ipaddr, opt, 4);
|
||||
sim_debug(DEBUG_DHCP, &imp_dev, ", router=%s", ipv4_inet_ntoa(ipaddr));
|
||||
opt += opt_len;
|
||||
break;
|
||||
case DHCP_OPTION_REQUESTED_IP:
|
||||
opt_len = *opt++;
|
||||
memcpy(&ipaddr, opt, 4);
|
||||
sim_debug(DEBUG_DHCP, &imp_dev, ", requested-ip=%s", ipv4_inet_ntoa(ipaddr));
|
||||
opt += opt_len;
|
||||
break;
|
||||
case DHCP_OPTION_LEASE_TIME:
|
||||
opt_len = *opt++;
|
||||
memcpy(&numeric, opt, 4);
|
||||
sim_debug(DEBUG_DHCP, &imp_dev, ", lease-time=%d", ntohl(numeric));
|
||||
opt += opt_len;
|
||||
break;
|
||||
case DHCP_OPTION_T1:
|
||||
opt_len = *opt++;
|
||||
memcpy(&numeric, opt, 4);
|
||||
sim_debug(DEBUG_DHCP, &imp_dev, ", renew-time=%d", ntohl(numeric));
|
||||
opt += opt_len;
|
||||
break;
|
||||
case DHCP_OPTION_T2:
|
||||
opt_len = *opt++;
|
||||
memcpy(&numeric, opt, 4);
|
||||
sim_debug(DEBUG_DHCP, &imp_dev, ", rebind-time=%d", ntohl(numeric));
|
||||
opt += opt_len;
|
||||
break;
|
||||
case DHCP_OPTION_SERVER_ID:
|
||||
opt_len = *opt++;
|
||||
memcpy(&ipaddr, opt, 4);
|
||||
sim_debug(DEBUG_DHCP, &imp_dev, ", server-ip=%s", ipv4_inet_ntoa(ipaddr));
|
||||
opt += opt_len;
|
||||
break;
|
||||
case DHCP_OPTION_MESSAGE_TYPE:
|
||||
opt_len = *opt++;
|
||||
sim_debug(DEBUG_DHCP, &imp_dev, "MessageType=%s", opr_names[*opt]);
|
||||
opt += opt_len;
|
||||
break;
|
||||
}
|
||||
}
|
||||
sim_debug(DEBUG_DHCP, &imp_dev, "\n");
|
||||
} else {
|
||||
if (udp->len && (imp_dev.dctrl & DEBUG_UDP))
|
||||
sim_data_trace(&imp_dev, imp_unit, payload + sizeof(struct udp), "",
|
||||
ntohs(udp->len), "", DEBUG_DATA);
|
||||
}
|
||||
break;
|
||||
case TCP_PROTO:
|
||||
tcp = (struct tcp *)payload;
|
||||
snprintf(src_port, sizeof(src_port), "%d", ntohs(tcp->tcp_sport));
|
||||
snprintf(dst_port, sizeof(dst_port), "%d", ntohs(tcp->tcp_dport));
|
||||
strlcpy(flags, "", sizeof(flags));
|
||||
for (flag=0; bits[flag].name; flag++) {
|
||||
if (ntohs(tcp->flags) & bits[flag].bitmask) {
|
||||
if (*flags)
|
||||
strlcat(flags, ",", sizeof(flags));
|
||||
strlcat(flags, bits[flag].name, sizeof(flags));
|
||||
}
|
||||
|
||||
}
|
||||
len = ntohs(ip->ip_len) - ((ip->ip_v_hl & 0xf) * 4 + (ntohs(tcp->flags) >> 12) * 4);
|
||||
sim_debug(DEBUG_TCP, &imp_dev, "%s %s%s %d byte packet from %s:%s to %s:%s\n", action,
|
||||
flags, *flags ? ":" : "", (int)len, src_ip, src_port, dst_ip, dst_port);
|
||||
if (len && (imp_dev.dctrl & DEBUG_TCP))
|
||||
sim_data_trace(&imp_dev, imp_unit, payload + 4 * (ntohs(tcp->flags) >> 12), "", len, "", DEBUG_DATA);
|
||||
break;
|
||||
case ICMP_PROTO:
|
||||
icmp = (struct icmp *)payload;
|
||||
len = ntohs(ip->ip_len) - (ip->ip_v_hl & 0xf) * 4;
|
||||
sim_debug(DEBUG_ICMP, &imp_dev, "%s %s %d byte packet from %s to %s\n", action,
|
||||
(icmp->type < sizeof(icmp_types)/sizeof(icmp_types[0])) ? icmp_types[icmp->type] : "", (int)len, src_ip, dst_ip);
|
||||
if (len && (imp_dev.dctrl & DEBUG_ICMP))
|
||||
sim_data_trace(&imp_dev, imp_unit, payload + sizeof(struct icmp), "", len, "", DEBUG_DATA);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void imp_write(struct imp_device *imp, ETH_PACK *packet) {
|
||||
imp_packet_debug(imp, "Sending", packet);
|
||||
eth_write(&imp->etherface, packet, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the ARP table, first use free entry, else use oldest.
|
||||
*/
|
||||
@@ -1365,6 +1658,7 @@ imp_arp_update(struct imp_device *imp, in_addr_T ipaddr, ETH_MAC *ethaddr, int a
|
||||
{
|
||||
struct arp_entry *tabptr;
|
||||
int i;
|
||||
char mac_buf[20];
|
||||
|
||||
/* Check if entry already in the table. */
|
||||
for (i = 0; i < IMP_ARPTAB_SIZE; i++) {
|
||||
@@ -1372,7 +1666,13 @@ imp_arp_update(struct imp_device *imp, in_addr_T ipaddr, ETH_MAC *ethaddr, int a
|
||||
|
||||
if (tabptr->ipaddr != 0) {
|
||||
if (tabptr->ipaddr == ipaddr) {
|
||||
memcpy(&tabptr->ethaddr, ethaddr, sizeof(ETH_MAC));
|
||||
if (0 != memcmp(&tabptr->ethaddr, ethaddr, sizeof(ETH_MAC))) {
|
||||
memcpy(&tabptr->ethaddr, ethaddr, sizeof(ETH_MAC));
|
||||
eth_mac_fmt(ethaddr, mac_buf);
|
||||
sim_debug(DEBUG_ARP, &imp_dev,
|
||||
"updating entry for IP %s to %s\n",
|
||||
ipv4_inet_ntoa(*((struct in_addr *)&ipaddr)), mac_buf);
|
||||
}
|
||||
if (tabptr->age != ARP_DONT_AGE)
|
||||
tabptr->age = age;
|
||||
return;
|
||||
@@ -1402,10 +1702,14 @@ imp_arp_update(struct imp_device *imp, in_addr_T ipaddr, ETH_MAC *ethaddr, int a
|
||||
tabptr = &imp->arp_table[fnd];
|
||||
}
|
||||
|
||||
/* Now update the entry */
|
||||
/* Now save the entry */
|
||||
memcpy(&tabptr->ethaddr, ethaddr, sizeof(ETH_MAC));
|
||||
tabptr->ipaddr = ipaddr;
|
||||
tabptr->age = age;
|
||||
eth_mac_fmt(ethaddr, mac_buf);
|
||||
sim_debug(DEBUG_ARP, &imp_dev,
|
||||
"creating entry for IP %s to %s, initial age=%d\n",
|
||||
ipv4_inet_ntoa(*((struct in_addr *)&ipaddr)), mac_buf, age);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1423,6 +1727,12 @@ void imp_arp_age(struct imp_device *imp)
|
||||
tabptr->age++; /* Age it */
|
||||
/* expire too old entries */
|
||||
if (tabptr->age > IMP_ARP_MAX_AGE) {
|
||||
char mac_buf[20];
|
||||
|
||||
eth_mac_fmt(&tabptr->ethaddr, mac_buf);
|
||||
sim_debug(DEBUG_ARP, &imp_dev,
|
||||
"discarding ARP entry for IP %s %s after %d seconds\n",
|
||||
ipv4_inet_ntoa(*((struct in_addr *)&tabptr->ipaddr)), mac_buf, IMP_ARP_MAX_AGE);
|
||||
memset(tabptr, 0, sizeof(*tabptr));
|
||||
}
|
||||
}
|
||||
@@ -1438,18 +1748,20 @@ void
|
||||
imp_arp_arpin(struct imp_device *imp, ETH_PACK *packet)
|
||||
{
|
||||
struct arp_hdr *arp;
|
||||
struct in_addr in_addr;
|
||||
int op;
|
||||
char mac_buf[20];
|
||||
|
||||
/* Ignore packet if too short */
|
||||
if (packet->len < sizeof(struct arp_hdr))
|
||||
return;
|
||||
arp = (struct arp_hdr *)(&packet->msg[0]);
|
||||
op = ntohs(arp->opcode);
|
||||
imp_arp_update(imp, arp->sipaddr, &arp->shwaddr, 0);
|
||||
|
||||
switch (op) {
|
||||
case ARP_REQUEST:
|
||||
if (arp->dipaddr == imp->ip) {
|
||||
imp_arp_update(imp, arp->sipaddr, &arp->shwaddr, 0);
|
||||
|
||||
arp->opcode = htons(ARP_REPLY);
|
||||
memcpy(&arp->dhwaddr, &arp->shwaddr, 6);
|
||||
@@ -1461,7 +1773,10 @@ imp_arp_arpin(struct imp_device *imp, ETH_PACK *packet)
|
||||
arp->sipaddr = imp->ip;
|
||||
arp->ethhdr.type = htons(ETHTYPE_ARP);
|
||||
packet->len = sizeof(struct arp_hdr);
|
||||
eth_write(&imp->etherface, packet, NULL);
|
||||
imp_write(imp, packet);
|
||||
eth_mac_fmt(&arp->dhwaddr, mac_buf);
|
||||
sim_debug(DEBUG_ARP, &imp_dev, "replied to received request for IP %s from %s\n",
|
||||
ipv4_inet_ntoa(*((struct in_addr *)&imp->ip)), mac_buf);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1469,7 +1784,11 @@ imp_arp_arpin(struct imp_device *imp, ETH_PACK *packet)
|
||||
/* Check if this is our address */
|
||||
if (arp->dipaddr == imp->ip) {
|
||||
struct imp_packet *nq = NULL; /* New send queue */
|
||||
imp_arp_update(imp, arp->sipaddr, &arp->shwaddr, 0);
|
||||
|
||||
eth_mac_fmt(&arp->shwaddr, mac_buf);
|
||||
memcpy(&in_addr, &arp->sipaddr, sizeof(in_addr));
|
||||
sim_debug(DEBUG_ARP, &imp_dev, "received reply for IP %s as %s\n",
|
||||
ipv4_inet_ntoa(in_addr), mac_buf);
|
||||
/* Scan send queue, and send all packets for this host */
|
||||
while (imp->sendq != NULL) {
|
||||
struct imp_packet *temp = imp->sendq;
|
||||
@@ -1481,7 +1800,7 @@ imp_arp_arpin(struct imp_device *imp, ETH_PACK *packet)
|
||||
memcpy(&pkt->ethhdr.dest, &arp->shwaddr, 6);
|
||||
memcpy(&pkt->ethhdr.src, &imp->mac, 6);
|
||||
pkt->ethhdr.type = htons(ETHTYPE_IP);
|
||||
eth_write(&imp->etherface, &temp->packet, NULL);
|
||||
imp_write(imp, &temp->packet);
|
||||
imp->rfnm_count++;
|
||||
imp_free_packet(imp, temp);
|
||||
} else {
|
||||
@@ -1522,7 +1841,8 @@ imp_arp_arpout(struct imp_device *imp, in_addr_T ipaddr)
|
||||
arp->protolen = 4;
|
||||
|
||||
arp_pkt.len = sizeof(struct arp_hdr);
|
||||
eth_write(&imp->etherface, &arp_pkt, NULL);
|
||||
imp_write(imp, &arp_pkt);
|
||||
sim_debug(DEBUG_ARP, &imp_dev, "sending request for IP %s\n", ipv4_inet_ntoa(*((struct in_addr *)&ipaddr)));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1625,7 +1945,9 @@ imp_do_send_dhcp(struct imp_device *imp,
|
||||
struct ip_hdr *pkt;
|
||||
struct udp *udp;
|
||||
struct udp_hdr udp_hdr;
|
||||
struct in_addr in_addr;
|
||||
int len;
|
||||
char mac_buf[20];
|
||||
|
||||
pkt = (struct ip_hdr *)(&packet->msg[0]);
|
||||
udp = (struct udp *)(&packet->msg[sizeof(struct imp_eth_hdr) +
|
||||
@@ -1658,9 +1980,13 @@ imp_do_send_dhcp(struct imp_device *imp,
|
||||
checksumadjust((uint8 *)&udp->chksum, (uint8 *)(&udp_hdr), 0,
|
||||
(uint8 *)(&udp_hdr), sizeof(udp_hdr));
|
||||
packet->len = len + sizeof(struct ip_hdr);
|
||||
eth_write(&imp->etherface, packet, NULL);
|
||||
sim_debug(DEBUG_DETAIL, &imp_dev,
|
||||
"DHCP client sent %s packet\n", op);
|
||||
imp_write(imp, packet);
|
||||
|
||||
eth_mac_fmt (&pkt->ethhdr.dest, mac_buf);
|
||||
memcpy(&in_addr, &udp_hdr.ip_dst, sizeof(in_addr));
|
||||
sim_debug(DEBUG_DHCP, &imp_dev,
|
||||
"client sent %s packet to: %s:%d(%s)\n",
|
||||
op, ipv4_inet_ntoa(in_addr), ntohs(udp->udp_dport), mac_buf);
|
||||
}
|
||||
|
||||
/* Handle incoming DCHP offer and other requests */
|
||||
@@ -1674,6 +2000,7 @@ imp_do_dhcp_client(struct imp_device *imp, ETH_PACK *read_buffer)
|
||||
struct dhcp *dhcp;
|
||||
struct udp *upkt;
|
||||
struct udp_hdr udp_hdr;
|
||||
struct in_addr in_addr;
|
||||
uint8 *opt;
|
||||
uint16 sum;
|
||||
int len;
|
||||
@@ -1685,6 +2012,7 @@ imp_do_dhcp_client(struct imp_device *imp, ETH_PACK *read_buffer)
|
||||
int rebind_time = 0; /* Rebind time */
|
||||
in_addr_T dhcpip = 0; /* DHCP server address */
|
||||
int opr = -1; /* DHCP operation */
|
||||
char mac_buf[20]; /* Source MAC address */
|
||||
|
||||
upkt = (struct udp *)(&((uint8 *)(ip_hdr))[hl]);
|
||||
dhcp = (struct dhcp *)(&((uint8 *)(upkt))[sizeof(struct udp)]);
|
||||
@@ -1771,10 +2099,13 @@ imp_do_dhcp_client(struct imp_device *imp, ETH_PACK *read_buffer)
|
||||
}
|
||||
}
|
||||
|
||||
sim_debug(DEBUG_DETAIL, &imp_dev,
|
||||
"DHCP client incoming %s packet: dhcp_state=%s - wait_time=%d\n",
|
||||
eth_mac_fmt(ð->src, mac_buf);
|
||||
memcpy(&in_addr, &udp_hdr.ip_src, sizeof(in_addr));
|
||||
sim_debug(DEBUG_DHCP, &imp_dev,
|
||||
"client incoming %s packet: dhcp_state=%s - wait_time=%d from: %s:%d(%s)\n",
|
||||
(opr == -1) ? "" : dhcp_opr_names[opr],
|
||||
dhcp_state_names[imp->dhcp_state], imp->dhcp_wait_time);
|
||||
dhcp_state_names[imp->dhcp_state], imp->dhcp_wait_time,
|
||||
ipv4_inet_ntoa(in_addr), ntohs(upkt->udp_sport), mac_buf);
|
||||
|
||||
/* Process an offer message */
|
||||
if (opr == DHCP_OFFER && imp->dhcp_state == DHCP_STATE_SELECTING) {
|
||||
@@ -1829,7 +2160,7 @@ imp_do_dhcp_client(struct imp_device *imp, ETH_PACK *read_buffer)
|
||||
arp->hwlen = 6;
|
||||
arp->protolen = 4;
|
||||
arp_pkt.len = sizeof(struct arp_hdr);
|
||||
eth_write(&imp->etherface, &arp_pkt, NULL);
|
||||
imp_write(imp, &arp_pkt);
|
||||
}
|
||||
}
|
||||
if (opr == DHCP_NAK && (imp->dhcp_state == DHCP_STATE_REQUESTING ||
|
||||
@@ -2338,7 +2669,7 @@ t_stat imp_attach(UNIT* uptr, CONST char* cptr)
|
||||
if (tptr == NULL) return SCPE_MEM;
|
||||
strcpy(tptr, cptr);
|
||||
|
||||
status = eth_open(&imp_data.etherface, cptr, &imp_dev, 0xFFFF);
|
||||
status = eth_open(&imp_data.etherface, cptr, &imp_dev, DEBUG_ETHER);
|
||||
if (status != SCPE_OK) {
|
||||
free(tptr);
|
||||
return status;
|
||||
|
||||
Reference in New Issue
Block a user