mirror of
https://github.com/Fishwaldo/u-boot.git
synced 2025-03-31 03:21:32 +00:00
net: tftpput: Add support for receiving ICMP packets
ICMP packets can tell you when there is no server at the other end. It is useful for tftp to figure this out, so that a quick error can be displayed, rather than pointlessly retrying. This adds an ICMP packet handler to the net interface. Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
parent
8f79bb17a4
commit
4793ee6522
2 changed files with 43 additions and 3 deletions
|
@ -48,6 +48,19 @@ typedef void rxhand_f(uchar *pkt, unsigned dport,
|
||||||
IPaddr_t sip, unsigned sport,
|
IPaddr_t sip, unsigned sport,
|
||||||
unsigned len);
|
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.
|
* A timeout handler. Called after time interval has expired.
|
||||||
*/
|
*/
|
||||||
|
@ -244,6 +257,7 @@ typedef struct
|
||||||
* ICMP stuff (just enough to handle (host) redirect messages)
|
* ICMP stuff (just enough to handle (host) redirect messages)
|
||||||
*/
|
*/
|
||||||
#define ICMP_ECHO_REPLY 0 /* Echo reply */
|
#define ICMP_ECHO_REPLY 0 /* Echo reply */
|
||||||
|
#define ICMP_NOT_REACH 3 /* Detination unreachable */
|
||||||
#define ICMP_REDIRECT 5 /* Redirect (change route) */
|
#define ICMP_REDIRECT 5 /* Redirect (change route) */
|
||||||
#define ICMP_ECHO_REQUEST 8 /* Echo request */
|
#define ICMP_ECHO_REQUEST 8 /* Echo request */
|
||||||
|
|
||||||
|
@ -251,6 +265,9 @@ typedef struct
|
||||||
#define ICMP_REDIR_NET 0 /* Redirect Net */
|
#define ICMP_REDIR_NET 0 /* Redirect Net */
|
||||||
#define ICMP_REDIR_HOST 1 /* Redirect Host */
|
#define ICMP_REDIR_HOST 1 /* Redirect Host */
|
||||||
|
|
||||||
|
/* Codes for NOT_REACH */
|
||||||
|
#define ICMP_NOT_REACH_PORT 3 /* Port unreachable */
|
||||||
|
|
||||||
typedef struct icmphdr {
|
typedef struct icmphdr {
|
||||||
uchar type;
|
uchar type;
|
||||||
uchar code;
|
uchar code;
|
||||||
|
@ -265,6 +282,7 @@ typedef struct icmphdr {
|
||||||
ushort __unused;
|
ushort __unused;
|
||||||
ushort mtu;
|
ushort mtu;
|
||||||
} frag;
|
} frag;
|
||||||
|
uchar data[0];
|
||||||
} un;
|
} un;
|
||||||
} ICMP_t;
|
} ICMP_t;
|
||||||
|
|
||||||
|
@ -397,6 +415,7 @@ extern uint NetCksum(uchar *, int); /* Calculate the checksum */
|
||||||
|
|
||||||
/* Set callbacks */
|
/* Set callbacks */
|
||||||
extern void NetSetHandler(rxhand_f *); /* Set RX packet handler */
|
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 */
|
extern void NetSetTimeout(ulong, thand_f *);/* Set timeout handler */
|
||||||
|
|
||||||
/* Transmit "NetTxPacket" */
|
/* Transmit "NetTxPacket" */
|
||||||
|
|
27
net/net.c
27
net/net.c
|
@ -215,6 +215,7 @@ volatile uchar *NetRxPackets[PKTBUFSRX];
|
||||||
|
|
||||||
/* Current RX packet handler */
|
/* Current RX packet handler */
|
||||||
static rxhand_f *packetHandler;
|
static rxhand_f *packetHandler;
|
||||||
|
static rxhand_icmp_f *packet_icmp_handler; /* Current ICMP rx handler */
|
||||||
/* Current timeout handler */
|
/* Current timeout handler */
|
||||||
static thand_f *timeHandler;
|
static thand_f *timeHandler;
|
||||||
/* Time base value */
|
/* Time base value */
|
||||||
|
@ -344,6 +345,7 @@ int
|
||||||
NetLoop(proto_t protocol)
|
NetLoop(proto_t protocol)
|
||||||
{
|
{
|
||||||
bd_t *bd = gd->bd;
|
bd_t *bd = gd->bd;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
NetRestarted = 0;
|
NetRestarted = 0;
|
||||||
NetDevExists = 0;
|
NetDevExists = 0;
|
||||||
|
@ -512,7 +514,7 @@ restart:
|
||||||
if (ctrlc()) {
|
if (ctrlc()) {
|
||||||
eth_halt();
|
eth_halt();
|
||||||
puts("\nAbort\n");
|
puts("\nAbort\n");
|
||||||
return -1;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArpTimeoutCheck();
|
ArpTimeoutCheck();
|
||||||
|
@ -564,12 +566,19 @@ restart:
|
||||||
setenv("fileaddr", buf);
|
setenv("fileaddr", buf);
|
||||||
}
|
}
|
||||||
eth_halt();
|
eth_halt();
|
||||||
return NetBootFileXferSize;
|
ret = NetBootFileXferSize;
|
||||||
|
goto done;
|
||||||
|
|
||||||
case NETLOOP_FAIL:
|
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;
|
packetHandler = f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void net_set_icmp_handler(rxhand_icmp_f *f)
|
||||||
|
{
|
||||||
|
packet_icmp_handler = f;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
NetSetTimeout(ulong iv, thand_f *f)
|
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;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1671,6 +1688,10 @@ NetReceive(volatile uchar *inpkt, int len)
|
||||||
* subnet. So this is probably a warning that your
|
* subnet. So this is probably a warning that your
|
||||||
* configuration might be wrong. But I'm not really
|
* configuration might be wrong. But I'm not really
|
||||||
* sure if there aren't any other situations.
|
* 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) {
|
if (ip->ip_p == IPPROTO_ICMP) {
|
||||||
receive_icmp(ip, len, src_ip, et);
|
receive_icmp(ip, len, src_ip, et);
|
||||||
|
|
Loading…
Add table
Reference in a new issue