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 d5d37b650..d7ff0687c 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); |