diff options
-rw-r--r-- | include/net.h | 19 | ||||
-rw-r--r-- | net/net.c | 27 |
2 files changed, 43 insertions, 3 deletions
diff --git a/include/net.h b/include/net.h index d5d37b6..d7ff068 100644 --- a/include/net.h +++ b/include/net.h @@ -48,6 +48,19 @@ typedef void rxhand_f(uchar *pkt, unsigned dport, 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. */ @@ -244,6 +257,7 @@ typedef struct * 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 */ @@ -251,6 +265,9 @@ typedef struct #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; @@ -265,6 +282,7 @@ typedef struct icmphdr { ushort __unused; ushort mtu; } frag; + uchar data[0]; } un; } ICMP_t; @@ -397,6 +415,7 @@ extern uint NetCksum(uchar *, int); /* Calculate the checksum */ /* 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" */ @@ -215,6 +215,7 @@ volatile uchar *NetRxPackets[PKTBUFSRX]; /* 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 */ @@ -344,6 +345,7 @@ int NetLoop(proto_t protocol) { bd_t *bd = gd->bd; + int ret = -1; NetRestarted = 0; NetDevExists = 0; @@ -512,7 +514,7 @@ restart: if (ctrlc()) { eth_halt(); puts("\nAbort\n"); - return -1; + goto done; } ArpTimeoutCheck(); @@ -564,12 +566,19 @@ restart: 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; } /**********************************************************************/ @@ -643,6 +652,10 @@ NetSetHandler(rxhand_f *f) packetHandler = f; } +void net_set_icmp_handler(rxhand_icmp_f *f) +{ + packet_icmp_handler = f; +} void NetSetTimeout(ulong iv, thand_f *f) @@ -1383,6 +1396,10 @@ static void receive_icmp(IP_t *ip, int len, IPaddr_t src_ip, Ethernet_t *et) 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; } } @@ -1671,6 +1688,10 @@ NetReceive(volatile uchar *inpkt, int len) * 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); |