IPaddr_t sip, unsigned sport,
unsigned len);
+/**
+ * An incoming ICMP packet handler.
+ * @param type ICMP type
+ * @param code ICMP code
+ * @param dport destination UDP port
+ * @param sip source IP address
+ * @param sport source UDP port
+ * @param pkt pointer to the ICMP packet data
+ * @param len packet length
+ */
+typedef void rxhand_icmp_f(unsigned type, unsigned code, unsigned dport,
+ IPaddr_t sip, unsigned sport, uchar *pkt, unsigned len);
+
/*
* A timeout handler. Called after time interval has expired.
*/
* ICMP stuff (just enough to handle (host) redirect messages)
*/
#define ICMP_ECHO_REPLY 0 /* Echo reply */
+#define ICMP_NOT_REACH 3 /* Detination unreachable */
#define ICMP_REDIRECT 5 /* Redirect (change route) */
#define ICMP_ECHO_REQUEST 8 /* Echo request */
#define ICMP_REDIR_NET 0 /* Redirect Net */
#define ICMP_REDIR_HOST 1 /* Redirect Host */
+/* Codes for NOT_REACH */
+#define ICMP_NOT_REACH_PORT 3 /* Port unreachable */
+
typedef struct icmphdr {
uchar type;
uchar code;
ushort __unused;
ushort mtu;
} frag;
+ uchar data[0];
} un;
} ICMP_t;
/* Set callbacks */
extern void NetSetHandler(rxhand_f *); /* Set RX packet handler */
+extern void net_set_icmp_handler(rxhand_icmp_f *f); /* Set ICMP RX handler */
extern void NetSetTimeout(ulong, thand_f *);/* Set timeout handler */
/* Transmit "NetTxPacket" */
/* Current RX packet handler */
static rxhand_f *packetHandler;
+static rxhand_icmp_f *packet_icmp_handler; /* Current ICMP rx handler */
/* Current timeout handler */
static thand_f *timeHandler;
/* Time base value */
NetLoop(proto_t protocol)
{
bd_t *bd = gd->bd;
+ int ret = -1;
NetRestarted = 0;
NetDevExists = 0;
if (ctrlc()) {
eth_halt();
puts("\nAbort\n");
- return -1;
+ goto done;
}
ArpTimeoutCheck();
setenv("fileaddr", buf);
}
eth_halt();
- return NetBootFileXferSize;
+ ret = NetBootFileXferSize;
+ goto done;
case NETLOOP_FAIL:
- return -1;
+ goto done;
}
}
+
+done:
+ /* Clear out the handlers */
+ NetSetHandler(NULL);
+ net_set_icmp_handler(NULL);
+ return ret;
}
/**********************************************************************/
packetHandler = f;
}
+void net_set_icmp_handler(rxhand_icmp_f *f)
+{
+ packet_icmp_handler = f;
+}
void
NetSetTimeout(ulong iv, thand_f *f)
break;
#endif
default:
+ if (packet_icmp_handler)
+ packet_icmp_handler(icmph->type, icmph->code,
+ ntohs(ip->udp_dst), src_ip, ntohs(ip->udp_src),
+ icmph->un.data, ntohs(ip->udp_len));
break;
}
}
* subnet. So this is probably a warning that your
* configuration might be wrong. But I'm not really
* sure if there aren't any other situations.
+ *
+ * Simon Glass <sjg@chromium.org>: We get an ICMP when
+ * we send a tftp packet to a dead connection, or when
+ * there is no server at the other end.
*/
if (ip->ip_p == IPPROTO_ICMP) {
receive_icmp(ip, len, src_ip, et);