From 258534718910c903451f1fe2e8fe1197c224c8e7 Mon Sep 17 00:00:00 2001 From: Stavros Passas Date: Fri, 20 Jan 2017 09:22:46 +0000 Subject: network: Fix DHCP client protocol Close #2877. --- cpukit/libnetworking/nfs/bootp_subr.c | 9 +++++++-- cpukit/libnetworking/rtems/bootp.h | 5 ++++- cpukit/libnetworking/rtems/rtems_dhcp.c | 28 +++++++++++++++++++++++++--- 3 files changed, 36 insertions(+), 6 deletions(-) diff --git a/cpukit/libnetworking/nfs/bootp_subr.c b/cpukit/libnetworking/nfs/bootp_subr.c index 3e71e95e08..b24ba945e7 100644 --- a/cpukit/libnetworking/nfs/bootp_subr.c +++ b/cpukit/libnetworking/nfs/bootp_subr.c @@ -284,7 +284,9 @@ int bootpc_call( struct bootp_packet *call, struct bootp_packet *reply, /* output */ - struct proc *procp) + struct proc *procp, + const void *exp_vend, + size_t exp_vend_len) { struct socket *so; struct sockaddr_in *sin; @@ -450,6 +452,9 @@ bootpc_call( if (bcmp(reply->chaddr,call->chaddr,call->hlen)) continue; + if (exp_vend_len > 0 && bcmp(exp_vend, reply->vend, exp_vend_len)) + continue; + goto gotreply; /* break two levels */ } /* while secs */ @@ -1051,7 +1056,7 @@ bootpc_init(bool update_files, bool forever) call.secs = 0; call.flags = htons(0x8000); /* We need an broadcast answer */ - error = bootpc_call(&call,&reply,procp); + error = bootpc_call(&call,&reply,procp, NULL, 0); if (!error) break; diff --git a/cpukit/libnetworking/rtems/bootp.h b/cpukit/libnetworking/rtems/bootp.h index d8eeb76f8f..4891430fce 100644 --- a/cpukit/libnetworking/rtems/bootp.h +++ b/cpukit/libnetworking/rtems/bootp.h @@ -3,6 +3,7 @@ #if !defined (__RTEMS_BOOTP_H__) #define __RTEMS_BOOTP_H__ +#include #include #if __cplusplus @@ -21,7 +22,9 @@ bool bootpc_init(bool, bool); int bootpc_call( struct bootp_packet *call, struct bootp_packet *reply, - struct proc *procp); + struct proc *procp, + const void *exp_vend, + size_t exp_vend_len); int bootpc_fakeup_interface(struct ifreq *ireq, struct socket *so, struct proc *procp); diff --git a/cpukit/libnetworking/rtems/rtems_dhcp.c b/cpukit/libnetworking/rtems/rtems_dhcp.c index fa7589071d..13c06bc732 100644 --- a/cpukit/libnetworking/rtems/rtems_dhcp.c +++ b/cpukit/libnetworking/rtems/rtems_dhcp.c @@ -760,7 +760,8 @@ dhcp_task (rtems_task_argument _sdl) /* * Send the Request. */ - error = bootpc_call ((struct bootp_packet *)&call, (struct bootp_packet *)&dhcp_req, procp); + error = bootpc_call ((struct bootp_packet *)&call, + (struct bootp_packet *)&dhcp_req, procp, NULL, 0); if (error) { rtems_bsdnet_semaphore_release (); printf ("DHCP call failed -- error %d", error); @@ -901,6 +902,7 @@ dhcp_init (int update_files) struct ifaddr *ifa; struct sockaddr_dl *sdl = NULL; struct proc *procp = NULL; + char expected_dhcp_payload[7]; clean_dns_entries(); @@ -957,15 +959,26 @@ dhcp_init (int update_files) return -1; } + /* * Build the DHCP Discover */ dhcp_discover_req (&call, sdl, &xid); + /* + * Expect a DHCP offer as response to DHCP discover + */ + memcpy(expected_dhcp_payload, dhcp_magic_cookie, sizeof(dhcp_magic_cookie)); + expected_dhcp_payload[sizeof(dhcp_magic_cookie) ]=0x35; /* DHCP */ + expected_dhcp_payload[sizeof(dhcp_magic_cookie)+1]=0x01; /* Length : 1 */ + expected_dhcp_payload[sizeof(dhcp_magic_cookie)+2]=0x02; /* DHCP_OFFER */ + /* * Send the Discover. */ - error = bootpc_call ((struct bootp_packet *)&call, (struct bootp_packet *)&reply, procp); + error = bootpc_call ((struct bootp_packet *)&call, + (struct bootp_packet *)&reply, procp, + expected_dhcp_payload, sizeof(expected_dhcp_payload)); if (error) { printf ("BOOTP call failed -- %s\n", strerror(error)); soclose (so); @@ -989,12 +1002,21 @@ dhcp_init (int update_files) return -1; } + /* + * Expect a DHCP_ACK as response to the DHCP REQUEST + * No need to reinitialize the whole expected_dhcp_payload variable, + * header and first two bytes of the payload are filled from DHCP offer + */ + expected_dhcp_payload[sizeof(dhcp_magic_cookie)+2]=0x05; /* DHCP_ACK */ + /* * Send a DHCP REQUEST */ dhcp_request_req (&call, &reply, sdl, true); - error = bootpc_call ((struct bootp_packet *)&call, (struct bootp_packet *)&reply, procp); + error = bootpc_call ((struct bootp_packet *)&call, + (struct bootp_packet *)&reply, procp, + expected_dhcp_payload, sizeof(expected_dhcp_payload)); if (error) { printf ("BOOTP call failed -- %s\n", strerror(error)); soclose (so); -- cgit v1.2.3