diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/link_local.c | 17 | ||||
-rw-r--r-- | net/nfs.c | 74 | ||||
-rw-r--r-- | net/tftp.c | 12 |
3 files changed, 72 insertions, 31 deletions
diff --git a/net/link_local.c b/net/link_local.c index 1ba796ebdf..4152fae5ba 100644 --- a/net/link_local.c +++ b/net/link_local.c @@ -206,6 +206,7 @@ void link_local_receive_arp(struct arp_hdr *arp, int len) { int source_ip_conflict; int target_ip_conflict; + IPaddr_t null_ip = 0; if (state == DISABLED) return; @@ -267,10 +268,18 @@ void link_local_receive_arp(struct arp_hdr *arp, int len) ) { source_ip_conflict = 1; } - if (arp->ar_op == htons(ARPOP_REQUEST) - && memcmp(&arp->ar_tpa, &ip, ARP_PLEN) == 0 - && memcmp(&arp->ar_tha, NetOurEther, ARP_HLEN) != 0 - ) { + + /* + * According to RFC 3927, section 2.2.1: + * Check if packet is an ARP probe by checking for a null source IP + * then check that target IP is equal to ours and source hw addr + * is not equal to ours. This condition should cause a conflict only + * during probe. + */ + if (arp->ar_op == htons(ARPOP_REQUEST) && + memcmp(&arp->ar_spa, &null_ip, ARP_PLEN) == 0 && + memcmp(&arp->ar_tpa, &ip, ARP_PLEN) == 0 && + memcmp(&arp->ar_sha, NetOurEther, ARP_HLEN) != 0) { target_ip_conflict = 1; } @@ -37,10 +37,14 @@ # define NFS_TIMEOUT CONFIG_NFS_TIMEOUT #endif +#define NFS_RPC_ERR 1 +#define NFS_RPC_DROP 124 + static int fs_mounted; static unsigned long rpc_id; static int nfs_offset = -1; static int nfs_len; +static ulong nfs_timeout = NFS_TIMEOUT; static char dirfh[NFS_FHSIZE]; /* file handle of directory */ static char filefh[NFS_FHSIZE]; /* file handle of kernel image */ @@ -399,8 +403,10 @@ rpc_lookup_reply(int prog, uchar *pkt, unsigned len) debug("%s\n", __func__); - if (ntohl(rpc_pkt.u.reply.id) != rpc_id) - return -1; + if (ntohl(rpc_pkt.u.reply.id) > rpc_id) + return -NFS_RPC_ERR; + else if (ntohl(rpc_pkt.u.reply.id) < rpc_id) + return -NFS_RPC_DROP; if (rpc_pkt.u.reply.rstatus || rpc_pkt.u.reply.verifier || @@ -428,8 +434,10 @@ nfs_mount_reply(uchar *pkt, unsigned len) memcpy((unsigned char *)&rpc_pkt, pkt, len); - if (ntohl(rpc_pkt.u.reply.id) != rpc_id) - return -1; + if (ntohl(rpc_pkt.u.reply.id) > rpc_id) + return -NFS_RPC_ERR; + else if (ntohl(rpc_pkt.u.reply.id) < rpc_id) + return -NFS_RPC_DROP; if (rpc_pkt.u.reply.rstatus || rpc_pkt.u.reply.verifier || @@ -452,8 +460,10 @@ nfs_umountall_reply(uchar *pkt, unsigned len) memcpy((unsigned char *)&rpc_pkt, pkt, len); - if (ntohl(rpc_pkt.u.reply.id) != rpc_id) - return -1; + if (ntohl(rpc_pkt.u.reply.id) > rpc_id) + return -NFS_RPC_ERR; + else if (ntohl(rpc_pkt.u.reply.id) < rpc_id) + return -NFS_RPC_DROP; if (rpc_pkt.u.reply.rstatus || rpc_pkt.u.reply.verifier || @@ -475,8 +485,10 @@ nfs_lookup_reply(uchar *pkt, unsigned len) memcpy((unsigned char *)&rpc_pkt, pkt, len); - if (ntohl(rpc_pkt.u.reply.id) != rpc_id) - return -1; + if (ntohl(rpc_pkt.u.reply.id) > rpc_id) + return -NFS_RPC_ERR; + else if (ntohl(rpc_pkt.u.reply.id) < rpc_id) + return -NFS_RPC_DROP; if (rpc_pkt.u.reply.rstatus || rpc_pkt.u.reply.verifier || @@ -499,8 +511,10 @@ nfs_readlink_reply(uchar *pkt, unsigned len) memcpy((unsigned char *)&rpc_pkt, pkt, len); - if (ntohl(rpc_pkt.u.reply.id) != rpc_id) - return -1; + if (ntohl(rpc_pkt.u.reply.id) > rpc_id) + return -NFS_RPC_ERR; + else if (ntohl(rpc_pkt.u.reply.id) < rpc_id) + return -NFS_RPC_DROP; if (rpc_pkt.u.reply.rstatus || rpc_pkt.u.reply.verifier || @@ -534,8 +548,10 @@ nfs_read_reply(uchar *pkt, unsigned len) memcpy((uchar *)&rpc_pkt, pkt, sizeof(rpc_pkt.u.reply)); - if (ntohl(rpc_pkt.u.reply.id) != rpc_id) - return -1; + if (ntohl(rpc_pkt.u.reply.id) > rpc_id) + return -NFS_RPC_ERR; + else if (ntohl(rpc_pkt.u.reply.id) < rpc_id) + return -NFS_RPC_DROP; if (rpc_pkt.u.reply.rstatus || rpc_pkt.u.reply.verifier || @@ -574,7 +590,8 @@ NfsTimeout(void) NetStartAgain(); } else { puts("T "); - NetSetTimeout(NFS_TIMEOUT, NfsTimeout); + NetSetTimeout(nfs_timeout + NFS_TIMEOUT * NfsTimeoutCount, + NfsTimeout); NfsSend(); } } @@ -583,6 +600,7 @@ static void NfsHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src, unsigned len) { int rlen; + int reply; debug("%s\n", __func__); @@ -591,19 +609,24 @@ NfsHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src, unsigned len) switch (NfsState) { case STATE_PRCLOOKUP_PROG_MOUNT_REQ: - rpc_lookup_reply(PROG_MOUNT, pkt, len); + if (rpc_lookup_reply(PROG_MOUNT, pkt, len) == -NFS_RPC_DROP) + break; NfsState = STATE_PRCLOOKUP_PROG_NFS_REQ; NfsSend(); break; case STATE_PRCLOOKUP_PROG_NFS_REQ: - rpc_lookup_reply(PROG_NFS, pkt, len); + if (rpc_lookup_reply(PROG_NFS, pkt, len) == -NFS_RPC_DROP) + break; NfsState = STATE_MOUNT_REQ; NfsSend(); break; case STATE_MOUNT_REQ: - if (nfs_mount_reply(pkt, len)) { + reply = nfs_mount_reply(pkt, len); + if (reply == -NFS_RPC_DROP) + break; + else if (reply == -NFS_RPC_ERR) { puts("*** ERROR: Cannot mount\n"); /* just to be sure... */ NfsState = STATE_UMOUNT_REQ; @@ -615,7 +638,10 @@ NfsHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src, unsigned len) break; case STATE_UMOUNT_REQ: - if (nfs_umountall_reply(pkt, len)) { + reply = nfs_umountall_reply(pkt, len); + if (reply == -NFS_RPC_DROP) + break; + else if (reply == -NFS_RPC_ERR) { puts("*** ERROR: Cannot umount\n"); net_set_state(NETLOOP_FAIL); } else { @@ -625,7 +651,10 @@ NfsHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src, unsigned len) break; case STATE_LOOKUP_REQ: - if (nfs_lookup_reply(pkt, len)) { + reply = nfs_lookup_reply(pkt, len); + if (reply == -NFS_RPC_DROP) + break; + else if (reply == -NFS_RPC_ERR) { puts("*** ERROR: File lookup fail\n"); NfsState = STATE_UMOUNT_REQ; NfsSend(); @@ -638,7 +667,10 @@ NfsHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src, unsigned len) break; case STATE_READLINK_REQ: - if (nfs_readlink_reply(pkt, len)) { + reply = nfs_readlink_reply(pkt, len); + if (reply == -NFS_RPC_DROP) + break; + else if (reply == -NFS_RPC_ERR) { puts("*** ERROR: Symlink fail\n"); NfsState = STATE_UMOUNT_REQ; NfsSend(); @@ -654,7 +686,7 @@ NfsHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src, unsigned len) case STATE_READ_REQ: rlen = nfs_read_reply(pkt, len); - NetSetTimeout(NFS_TIMEOUT, NfsTimeout); + NetSetTimeout(nfs_timeout, NfsTimeout); if (rlen > 0) { nfs_offset += rlen; NfsSend(); @@ -738,7 +770,7 @@ NfsStart(void) printf("\nLoad address: 0x%lx\n" "Loading: *\b", load_addr); - NetSetTimeout(NFS_TIMEOUT, NfsTimeout); + NetSetTimeout(nfs_timeout, NfsTimeout); net_set_udp_handler(NfsHandler); NfsTimeoutCount = 0; diff --git a/net/tftp.c b/net/tftp.c index 09790eb7cf..6d333d559c 100644 --- a/net/tftp.c +++ b/net/tftp.c @@ -446,8 +446,8 @@ static void TftpHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src, unsigned len) { - ushort proto; - ushort *s; + __be16 proto; + __be16 *s; int i; if (dest != TftpOurPort) { @@ -465,7 +465,7 @@ TftpHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src, return; len -= 2; /* warning: don't use increment (++) in ntohs() macros!! */ - s = (ushort *)pkt; + s = (__be16 *)pkt; proto = *s++; pkt = (uchar *)s; switch (ntohs(proto)) { @@ -556,7 +556,7 @@ TftpHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src, if (len < 2) return; len -= 2; - TftpBlock = ntohs(*(ushort *)pkt); + TftpBlock = ntohs(*(__be16 *)pkt); update_block_number(); @@ -644,9 +644,9 @@ TftpHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src, case TFTP_ERROR: printf("\nTFTP error: '%s' (%d)\n", - pkt + 2, ntohs(*(ushort *)pkt)); + pkt + 2, ntohs(*(__be16 *)pkt)); - switch (ntohs(*(ushort *)pkt)) { + switch (ntohs(*(__be16 *)pkt)) { case TFTP_ERR_FILE_NOT_FOUND: case TFTP_ERR_ACCESS_DENIED: puts("Not retrying...\n"); |