diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2007-10-31 23:27:55 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2007-10-31 23:27:55 +0000 |
commit | be3873f03972b44e95458345b5ab73b1b75e2eee (patch) | |
tree | 2fc5881e116bb36f5d6c6f2ae8ed86456b96c2cf /nuttx/net | |
parent | a76a953e2fb34a521faac9c66207c08f77da9ce5 (diff) | |
download | px4-nuttx-be3873f03972b44e95458345b5ab73b1b75e2eee.tar.gz px4-nuttx-be3873f03972b44e95458345b5ab73b1b75e2eee.tar.bz2 px4-nuttx-be3873f03972b44e95458345b5ab73b1b75e2eee.zip |
in progress update
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@360 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/net')
-rw-r--r-- | nuttx/net/connect.c | 291 | ||||
-rw-r--r-- | nuttx/net/recvfrom.c | 24 | ||||
-rw-r--r-- | nuttx/net/uip/uip-arp.c | 302 |
3 files changed, 449 insertions, 168 deletions
diff --git a/nuttx/net/connect.c b/nuttx/net/connect.c index 579972d99..35c3b9e0d 100644 --- a/nuttx/net/connect.c +++ b/nuttx/net/connect.c @@ -43,10 +43,37 @@ #include <sys/types.h> #include <sys/socket.h> #include <errno.h> +#include <arch/irq.h> #include "net-internal.h" /**************************************************************************** + * Private Types + ****************************************************************************/ + +struct tcp_connect_s +{ + FAR struct uip_conn *tc_conn; /* Reference to TCP connection structure */ + sem_t tc_sem; /* Semaphore signals recv completion */ + int tc_result; /* OK on success, otherwise a negated errno. */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void connection_event(void *private); +static inline void tcp_setup_callbacks(struct uip_conn *conn, FAR struct socket *psock, + FAR struct tcp_connect_s *pstate); +static inline void tcp_teardown_callbacks(struct uip_conn *conn, int status); +static void tcp_connect_interrupt(struct uip_driver_s *dev, void *private); +#ifdef CONFIG_NET_IPv6 +static inline int tcp_connect(FAR struct socket *psock, const struct sockaddr_in6 *inaddr); +#else +static inline int tcp_connect(FAR struct socket *psock, const struct sockaddr_in *inaddr); +#endif + +/**************************************************************************** * Private Functions ****************************************************************************/ /**************************************************************************** @@ -78,7 +105,7 @@ static void connection_event(void *private) */ if ((uip_flags & (UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT)) != 0) { - /* Indicate that the socet is no longer connected */ + /* Indicate that the socket is no longer connected */ psock->s_flags &= ~_SF_CONNECTED; } @@ -87,7 +114,7 @@ static void connection_event(void *private) else if ((uip_flags & UIP_CONNECTED) != 0) { - /* Indicate that the socet is no longer connected */ + /* Indicate that the socket is now connected */ psock->s_flags |= _SF_CONNECTED; } @@ -95,6 +122,237 @@ static void connection_event(void *private) } /**************************************************************************** + * Function: tcp_setup_callbacks + ****************************************************************************/ + +static inline void tcp_setup_callbacks(struct uip_conn *conn, FAR struct socket *psock, + FAR struct tcp_connect_s *pstate) +{ + /* Set up the callbacks in the connection */ + + conn->data_private = (void*)pstate; + conn->data_event = tcp_connect_interrupt; + + /* Set up to receive callbacks on connection-related events */ + + conn->connection_private = (void*)psock; + conn->connection_event = connection_event; +} + +/**************************************************************************** + * Function: tcp_teardown_callbacks + ****************************************************************************/ + +static inline void tcp_teardown_callbacks(struct uip_conn *conn, int status) +{ + /* Make sure that no further interrupts are processed */ + + conn->data_private = NULL; + conn->data_event = NULL; + + /* If we successfully connected, we will continue to monitor the connection state + * via callbacks. + */ + + if (status < 0) + { + /* Failed to connect */ + + conn->connection_private = NULL; + conn->connection_event = NULL; + } +} + +/**************************************************************************** + * Function: tcp_connect_interrupt + * + * Description: + * This function is called from the interrupt level to perform the actual + * connection operation via by the uIP layer. + * + * Parameters: + * dev The sructure of the network driver that caused the interrupt + * private An instance of struct recvfrom_s cast to void* + * + * Returned Value: + * None + * + * Assumptions: + * Running at the interrupt level + * + ****************************************************************************/ + +static void tcp_connect_interrupt(struct uip_driver_s *dev, void *private) +{ + struct tcp_connect_s *pstate = (struct tcp_connect_s *)private; + + /* 'private' might be null in some race conditions (?) */ + + if (pstate) + { + /* The following errors should be detected here (someday) + * + * ECONNREFUSED + * No one listening on the remote address. + * ENETUNREACH + * Network is unreachable. + * ETIMEDOUT + * Timeout while attempting connection. The server may be too busy + * to accept new connections. + */ + + /* UIP_CLOSE: The remote host has closed the connection + * UIP_ABORT: The remote host has aborted the connection + */ + + if ((uip_flags & (UIP_CLOSE|UIP_ABORT)) != 0) + { + /* Indicate that remote host refused the connection */ + + pstate->tc_result = -ECONNREFUSED; + } + + /* UIP_TIMEDOUT: Connection aborted due to too many retransmissions. */ + + else if ((uip_flags & UIP_TIMEDOUT) != 0) + { + /* Indicate that the remote host is unreachable (or should this be timedout?) */ + + pstate->tc_result = -ECONNREFUSED; + } + + /* UIP_CONNECTED: The socket is successfully connected */ + + else if ((uip_flags & UIP_CONNECTED) != 0) + { + /* Indicate that the socket is no longer connected */ + + pstate->tc_result = OK; + } + + /* Otherwise, it is not an event of importance to us at the moment */ + + else + { + return; + } + + /* Stop further callbacks */ + + tcp_teardown_callbacks(pstate->tc_conn, pstate->tc_result); + + /* Wake up the waiting thread */ + + sem_post(&pstate->tc_sem); + } +} + +/**************************************************************************** + * Function: tcp_connect + * + * Description: + * Perform a TCP connection + * + * Parameters: + * psock A reference to the socket structure of the socket to be connected + * inaddr The address of the remote server to connect to + * + * Returned Value: + * None + * + * Assumptions: + * Running at the interrupt level + * + ****************************************************************************/ + +#ifdef CONFIG_NET_IPv6 +static inline int tcp_connect(FAR struct socket *psock, const struct sockaddr_in6 *inaddr) +#else +static inline int tcp_connect(FAR struct socket *psock, const struct sockaddr_in *inaddr) +#endif +{ + FAR struct uip_conn *conn; + struct tcp_connect_s state; + irqstate_t flags; + int ret = OK; + + /* Interrupts must be disabled through all of the following because + * we cannot allow the network callback to occur until we are completely + * setup. + */ + + flags = irqsave(); + + /* Get the connection reference from the socket */ + + conn = psock->s_conn; + if (!conn) /* Should always be non-NULL */ + { + ret = -EINVAL; + } + else + { + /* Perform the uIP connection operation */ + + ret = uip_tcpconnect(conn, inaddr); + } + + if (ret >= 0) + { + /* Initialize the TCP state structure */ + + (void)sem_init(&state.tc_sem, 0, 0); /* Doesn't really fail */ + state.tc_conn = conn; + state.tc_result = -EAGAIN; + + /* Set up the callbacks in the connection */ + + tcp_setup_callbacks(conn, psock, &state); + + /* Wait for either the connect to complete or for an error/timeout to occur. + * NOTES: (1) sem_wait will also terminate if a signal is received, (2) + * interrupts are disabled! They will be re-enabled while the task sleeps + * and automatically re-enabled when the task restarts. + */ + + ret = sem_wait(&state.tc_sem); + + /* Uninitialize the state structure */ + + (void)sem_destroy(&state.tc_sem); + + /* If sem_wait failed, recover the negated error (probably -EINTR) */ + + if (ret < 0) + { + int err = *get_errno_ptr(); + if (err >= 0) + { + err = ENOSYS; + } + ret = -err; + } + else + { + /* If the wait succeeded, then get the new error value from the state structure */ + + ret = state.tc_result; + } + + /* Make sure that no further interrupts are processed */ + tcp_teardown_callbacks(conn, ret); + + /* Mark the connection bound and connected */ + if (ret >= 0) + { + psock->s_flags |= (_SF_BOUND|_SF_CONNECTED); + } + } + irqrestore(flags); + return ret; +} + +/**************************************************************************** * Public Functions ****************************************************************************/ @@ -204,38 +462,21 @@ int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { case SOCK_STREAM: { - struct uip_conn *conn; - /* Verify that the socket is not already connected */ if (_SS_ISCONNECTED(psock->s_flags)) { - err = -EISCONN; + err = EISCONN; goto errout; } - /* Get the connection reference from the socket */ + /* Its not ... connect it */ - conn = psock->s_conn; - if (conn) /* Should always be non-NULL */ + ret = tcp_connect(psock, inaddr); + if (ret < 0) { - /* Perform the uIP connection operation */ - - ret = uip_tcpconnect(psock->s_conn, inaddr); - if (ret < 0) - { - err = -ret; - goto errout; - } - - /* Mark the connection bound and connected */ - - psock->s_flags |= (_SF_BOUND|_SF_CONNECTED); - - /* Set up to receive callbacks on connection-related events */ - - conn->connection_private = (void*)psock; - conn->connection_event = connection_event; + err = -ret; + goto errout; } } break; diff --git a/nuttx/net/recvfrom.c b/nuttx/net/recvfrom.c index c13ada6e6..25dc1c4fb 100644 --- a/nuttx/net/recvfrom.c +++ b/nuttx/net/recvfrom.c @@ -64,13 +64,11 @@ struct recvfrom_s { #if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK) FAR struct socket *rf_sock; /* The parent socket structure */ + uint32 rf_starttime; /* rcv start time for determining timeout */ #endif sem_t rf_sem; /* Semaphore signals recv completion */ size_t rf_buflen; /* Length of receive buffer */ char *rf_buffer; /* Pointer to receive buffer */ -#ifndef CONFIG_DISABLE_CLOCK - uint32 rf_starttime; /* rcv start time for determining timeout */ -#endif size_t rf_recvlen; /* The received length */ int rf_result; /* OK on success, otherwise a negated errno. */ }; @@ -101,16 +99,20 @@ struct recvfrom_s static void recvfrom_interrupt(struct uip_driver_s *dev, void *private) { struct recvfrom_s *pstate = (struct recvfrom_s *)private; +#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK) FAR struct socket *psock; +#endif size_t recvlen; /* 'private' might be null in some race conditions (?) */ if (pstate) { +#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK) /* Get the socket reference from the private data */ psock = pstate->rf_sock; +#endif /* If new data is available, then complete the read action. */ @@ -184,7 +186,7 @@ static void recvfrom_interrupt(struct uip_driver_s *dev, void *private) * the TCP receive. */ -#ifndef CONFIG_DISABLE_CLOCK +#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK) pstate->rf_starttime = g_system_timer; #endif } @@ -223,7 +225,7 @@ static void recvfrom_interrupt(struct uip_driver_s *dev, void *private) * poll -- check for a timeout. */ -#ifndef CONFIG_DISABLE_CLOCK +#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK) else { socktimeo_t timeo; @@ -240,16 +242,12 @@ static void recvfrom_interrupt(struct uip_driver_s *dev, void *private) } /* No.. check for a timeout configured via setsockopts(SO_RCVTIMEO). - * If non... we well let the read hang forever. + * If none... we well let the read hang forever. */ else { -#ifdef CONFIG_NET_SOCKOPTS timeo = psock->s_rcvtimeo; -#else - timeo = 0; -#endif } /* Is there an effective timeout? */ @@ -337,13 +335,13 @@ static void recvfrom_init(FAR struct socket *psock, FAR void *buf, size_t len, memset(pstate, 0, sizeof(struct recvfrom_s)); (void)sem_init(&pstate->rf_sem, 0, 0); /* Doesn't really fail */ - pstate->rf_sock = psock; pstate->rf_buflen = len; pstate->rf_buffer = buf; -#ifndef CONFIG_DISABLE_CLOCK +#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK) /* Set up the start time for the timeout */ + pstate->rf_sock = psock; pstate->rf_starttime = g_system_timer; #endif } @@ -542,7 +540,7 @@ static ssize_t tcp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len, * and automatically re-enabled when the task restarts. */ - ret = sem_wait(&state. rf_sem); + ret = sem_wait(&state.rf_sem); /* Make sure that no further interrupts are processed */ diff --git a/nuttx/net/uip/uip-arp.c b/nuttx/net/uip/uip-arp.c index 87e48a609..7b242156c 100644 --- a/nuttx/net/uip/uip-arp.c +++ b/nuttx/net/uip/uip-arp.c @@ -1,22 +1,20 @@ -/* uip-arp.c +/**************************************************************************** + * net/uip/uip-arp.c * Implementation of the ARP Address Resolution Protocol. - * Author: Adam Dunkels <adam@dunkels.com> * - * The Address Resolution Protocol ARP is used for mapping between IP - * addresses and link level addresses such as the Ethernet MAC - * addresses. ARP uses broadcast queries to ask for the link level - * address of a known IP address and the host which is configured with - * the IP address for which the query was meant, will respond with its - * link level address. + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> * - * Note: This ARP implementation only supports Ethernet. + * Based on uIP which also has a BSD style license: * - * Copyright (c) 2001-2003, Adam Dunkels. - * All rights reserved. + * Author: Adam Dunkels <adam@dunkels.com> + * Copyright (c) 2001-2003, Adam Dunkels. + * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: + * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright @@ -37,8 +35,23 @@ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* The Address Resolution Protocol ARP is used for mapping between IP + * addresses and link level addresses such as the Ethernet MAC + * addresses. ARP uses broadcast queries to ask for the link level + * address of a known IP address and the host which is configured with + * the IP address for which the query was meant, will respond with its + * link level address. + * + * Note: This ARP implementation only supports Ethernet. */ +/**************************************************************************** + * Included Files + ****************************************************************************/ + #include <sys/types.h> #include <sys/ioctl.h> #include <string.h> @@ -46,99 +59,82 @@ #include <net/uip/uip-arch.h> #include <net/uip/uip-arp.h> +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define ARP_REQUEST 1 +#define ARP_REPLY 2 + +#define ARP_HWTYPE_ETH 1 + +#define BUF ((struct arp_hdr *)&dev->d_buf[0]) +#define IPBUF ((struct ethip_hdr *)&dev->d_buf[0]) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + struct arp_hdr { - struct uip_eth_hdr ethhdr; - uint16 hwtype; - uint16 protocol; - uint8 hwlen; - uint8 protolen; - uint16 opcode; - struct uip_eth_addr shwaddr; - in_addr_t sipaddr; - struct uip_eth_addr dhwaddr; - in_addr_t dipaddr; + struct uip_eth_hdr ah_ethhdr; + uint16 ah_hwtype; + uint16 ah_protocol; + uint8 ah_hwlen; + uint8 ah_protolen; + uint16 ah_opcode; + struct uip_eth_addr ah_shwaddr; + uint16 ah_sipaddr[2]; + struct uip_eth_addr ah_dhwaddr; + uint16 ah_dipaddr[2]; }; struct ethip_hdr { - struct uip_eth_hdr ethhdr; + struct uip_eth_hdr eh_ethhdr; /* IP header. */ - uint8 vhl; - uint8 tos; - uint8 len[2]; - uint8 ipid[2]; - uint8 ipoffset[2]; - uint8 ttl; - uint8 proto; - uint16 ipchksum; - uint16 srcipaddr[2]; - uint16 destipaddr[2]; + uint8 eh_vhl; + uint8 eh_tos; + uint8 eh_len[2]; + uint8 eh_ipid[2]; + uint8 eh_ipoffset[2]; + uint8 eh_ttl; + uint8 eh_proto; + uint16 eh_ipchksum; + uint16 eh_srcipaddr[2]; + uint16 eh_destipaddr[2]; }; -#define ARP_REQUEST 1 -#define ARP_REPLY 2 - -#define ARP_HWTYPE_ETH 1 - struct arp_entry { - in_addr_t ipaddr; - struct uip_eth_addr ethaddr; - uint8 time; + in_addr_t at_ipaddr; + struct uip_eth_addr at_ethaddr; + uint8 at_time; }; +/**************************************************************************** + * Private Data + ****************************************************************************/ + static const struct uip_eth_addr broadcast_ethaddr = - {{0xff,0xff,0xff,0xff,0xff,0xff}}; -static const uint16 broadcast_ipaddr[2] = {0xffff,0xffff}; + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}; +static const uint16 broadcast_ipaddr[2] = {0xffff, 0xffff}; static struct arp_entry arp_table[UIP_ARPTAB_SIZE]; -static in_addr_t ipaddr; -static uint8 i, c; - -static uint8 arptime; -static uint8 tmpage; - -#define BUF ((struct arp_hdr *)&dev->d_buf[0]) -#define IPBUF ((struct ethip_hdr *)&dev->d_buf[0]) - -/* Initialize the ARP module. */ - -void uip_arp_init(void) -{ - for (i = 0; i < UIP_ARPTAB_SIZE; ++i) - { - memset(&arp_table[i].ipaddr, 0, sizeof(in_addr_t)); - } -} +static uint8 g_arptime; -/* Periodic ARP processing function. - * - * This function performs periodic timer processing in the ARP module - * and should be called at regular intervals. The recommended interval - * is 10 seconds between the calls. - */ -void uip_arp_timer(void) -{ - struct arp_entry *tabptr; - - ++arptime; - for (i = 0; i < UIP_ARPTAB_SIZE; ++i) - { - tabptr = &arp_table[i]; - if (tabptr->ipaddr != 0 && arptime - tabptr->time >= UIP_ARP_MAXAGE) - { - tabptr->ipaddr = 0; - } - } -} +/**************************************************************************** + * Private Functions + ****************************************************************************/ -static void uip_arp_update(in_addr_t pipaddr, struct uip_eth_addr *ethaddr) +static void uip_arp_update(uint16 *pipaddr, struct uip_eth_addr *ethaddr) { struct arp_entry *tabptr; + in_addr_t ipaddr = uip_ip4addr_conv(pipaddr); + int i; /* Walk through the ARP mapping table and try to find an entry to * update. If none is found, the IP -> MAC address mapping is @@ -151,17 +147,17 @@ static void uip_arp_update(in_addr_t pipaddr, struct uip_eth_addr *ethaddr) /* Only check those entries that are actually in use. */ - if (tabptr->ipaddr != 0) + if (tabptr->at_ipaddr != 0) { /* Check if the source IP address of the incoming packet matches * the IP address in this ARP table entry. */ - if (uip_ipaddr_cmp(pipaddr, tabptr->ipaddr)) + if (uip_ipaddr_cmp(ipaddr, tabptr->at_ipaddr)) { /* An old entry found, update this and return. */ - memcpy(tabptr->ethaddr.addr, ethaddr->addr, IFHWADDRLEN); - tabptr->time = arptime; + memcpy(tabptr->at_ethaddr.addr, ethaddr->addr, IFHWADDRLEN); + tabptr->at_time = g_arptime; return; } @@ -176,7 +172,7 @@ static void uip_arp_update(in_addr_t pipaddr, struct uip_eth_addr *ethaddr) for (i = 0; i < UIP_ARPTAB_SIZE; ++i) { tabptr = &arp_table[i]; - if (tabptr->ipaddr == 0) + if (tabptr->at_ipaddr == 0) { break; } @@ -188,18 +184,18 @@ static void uip_arp_update(in_addr_t pipaddr, struct uip_eth_addr *ethaddr) if (i == UIP_ARPTAB_SIZE) { - tmpage = 0; - c = 0; + uint8 tmpage = 0; + int j = 0; for (i = 0; i < UIP_ARPTAB_SIZE; ++i) { tabptr = &arp_table[i]; - if (arptime - tabptr->time > tmpage) + if (g_arptime - tabptr->at_time > tmpage) { - tmpage = arptime - tabptr->time; - c = i; + tmpage = g_arptime - tabptr->at_time; + j = i; } } - i = c; + i = j; tabptr = &arp_table[i]; } @@ -207,9 +203,47 @@ static void uip_arp_update(in_addr_t pipaddr, struct uip_eth_addr *ethaddr) * information. */ - tabptr->ipaddr = pipaddr; - memcpy(tabptr->ethaddr.addr, ethaddr->addr, IFHWADDRLEN); - tabptr->time = arptime; + tabptr->at_ipaddr = ipaddr; + memcpy(tabptr->at_ethaddr.addr, ethaddr->addr, IFHWADDRLEN); + tabptr->at_time = g_arptime; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/* Initialize the ARP module. */ + +void uip_arp_init(void) +{ + int i; + for (i = 0; i < UIP_ARPTAB_SIZE; ++i) + { + memset(&arp_table[i].at_ipaddr, 0, sizeof(in_addr_t)); + } +} + +/* Periodic ARP processing function. + * + * This function performs periodic timer processing in the ARP module + * and should be called at regular intervals. The recommended interval + * is 10 seconds between the calls. + */ + +void uip_arp_timer(void) +{ + struct arp_entry *tabptr; + int i; + + ++g_arptime; + for (i = 0; i < UIP_ARPTAB_SIZE; ++i) + { + tabptr = &arp_table[i]; + if (tabptr->at_ipaddr != 0 && g_arptime - tabptr->at_time >= UIP_ARP_MAXAGE) + { + tabptr->at_ipaddr = 0; + } + } } /* ARP processing for incoming IP packets @@ -231,12 +265,12 @@ void uip_arp_ipin(void) /* Only insert/update an entry if the source IP address of the incoming IP packet comes from a host on the local network. */ - if ((IPBUF->srcipaddr & dev->d_netmask) != (dev->d_ipaddr & dev->d_netmask)) + if ((IPBUF->eh_srcipaddr & dev->d_netmask) != (dev->d_ipaddr & dev->d_netmask)) { return; } - uip_arp_update(IPBUF->srcipaddr, &(IPBUF->ethhdr.src)); + uip_arp_update(IPBUF->eh_srcipaddr, &(IPBUF->eh_ethhdr.src)); } #endif /* 0 */ @@ -263,6 +297,7 @@ void uip_arp_ipin(void) void uip_arp_arpin(struct uip_driver_s *dev) { + in_addr_t ipaddr; if (dev->d_len < sizeof(struct arp_hdr)) { dev->d_len = 0; @@ -270,33 +305,36 @@ void uip_arp_arpin(struct uip_driver_s *dev) } dev->d_len = 0; - switch(BUF->opcode) + ipaddr = uip_ip4addr_conv(BUF->ah_dipaddr); + switch(BUF->ah_opcode) { case HTONS(ARP_REQUEST): /* ARP request. If it asked for our address, we send out a reply. */ - if (uip_ipaddr_cmp(BUF->dipaddr, dev->d_ipaddr)) + if (uip_ipaddr_cmp(ipaddr, dev->d_ipaddr)) { /* First, we register the one who made the request in our ARP * table, since it is likely that we will do more communication * with this host in the future. */ - uip_arp_update(BUF->sipaddr, &BUF->shwaddr); + uip_arp_update(BUF->ah_sipaddr, &BUF->ah_shwaddr); /* The reply opcode is 2. */ - BUF->opcode = HTONS(2); + BUF->ah_opcode = HTONS(2); - memcpy(BUF->dhwaddr.addr, BUF->shwaddr.addr, IFHWADDRLEN); - memcpy(BUF->shwaddr.addr, dev->d_mac.addr, IFHWADDRLEN); - memcpy(BUF->ethhdr.src.addr, dev->d_mac.addr, IFHWADDRLEN); - memcpy(BUF->ethhdr.dest.addr, BUF->dhwaddr.addr, IFHWADDRLEN); + memcpy(BUF->ah_dhwaddr.addr, BUF->ah_shwaddr.addr, IFHWADDRLEN); + memcpy(BUF->ah_shwaddr.addr, dev->d_mac.addr, IFHWADDRLEN); + memcpy(BUF->ah_ethhdr.src.addr, dev->d_mac.addr, IFHWADDRLEN); + memcpy(BUF->ah_ethhdr.dest.addr, BUF->ah_dhwaddr.addr, IFHWADDRLEN); - BUF->dipaddr = BUF->sipaddr; - BUF->sipaddr = dev->d_ipaddr; + BUF->ah_dipaddr[0] = BUF->ah_sipaddr[0]; + BUF->ah_dipaddr[1] = BUF->ah_sipaddr[1]; + BUF->ah_sipaddr[0] = dev->d_ipaddr >> 16; + BUF->ah_sipaddr[1] = dev->d_ipaddr & 0xffff; - BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP); + BUF->ah_ethhdr.type = HTONS(UIP_ETHTYPE_ARP); dev->d_len = sizeof(struct arp_hdr); } break; @@ -306,9 +344,9 @@ void uip_arp_arpin(struct uip_driver_s *dev) * for us. */ - if (uip_ipaddr_cmp(BUF->dipaddr, dev->d_ipaddr)) + if (uip_ipaddr_cmp(ipaddr, dev->d_ipaddr)) { - uip_arp_update(BUF->sipaddr, &BUF->shwaddr); + uip_arp_update(BUF->ah_sipaddr, &BUF->ah_shwaddr); } break; } @@ -342,6 +380,9 @@ void uip_arp_arpin(struct uip_driver_s *dev) void uip_arp_out(struct uip_driver_s *dev) { struct arp_entry *tabptr; + in_addr_t ipaddr; + in_addr_t destipaddr; + int i; /* Find the destination IP address in the ARP table and construct the Ethernet header. If the destination IP addres isn't on the @@ -352,15 +393,16 @@ void uip_arp_out(struct uip_driver_s *dev) /* First check if destination is a local broadcast. */ - if (uiphdr_ipaddr_cmp(IPBUF->destipaddr, broadcast_ipaddr)) + if (uiphdr_ipaddr_cmp(IPBUF->eh_destipaddr, broadcast_ipaddr)) { - memcpy(IPBUF->ethhdr.dest.addr, broadcast_ethaddr.addr, IFHWADDRLEN); + memcpy(IPBUF->eh_ethhdr.dest.addr, broadcast_ethaddr.addr, IFHWADDRLEN); } else { /* Check if the destination address is on the local network. */ - if (!uip_ipaddr_maskcmp(IPBUF->destipaddr, dev->d_ipaddr, dev->d_netmask)) + destipaddr = uip_ip4addr_conv(IPBUF->eh_destipaddr); + if (!uip_ipaddr_maskcmp(destipaddr, dev->d_ipaddr, dev->d_netmask)) { /* Destination address was not on the local network, so we need to * use the default router's IP address instead of the destination @@ -373,13 +415,13 @@ void uip_arp_out(struct uip_driver_s *dev) { /* Else, we use the destination IP address. */ - uip_ipaddr_copy(ipaddr, IPBUF->destipaddr); + uip_ipaddr_copy(ipaddr, destipaddr); } for (i = 0; i < UIP_ARPTAB_SIZE; ++i) { tabptr = &arp_table[i]; - if (uip_ipaddr_cmp(ipaddr, tabptr->ipaddr)) + if (uip_ipaddr_cmp(ipaddr, tabptr->at_ipaddr)) { break; } @@ -391,19 +433,19 @@ void uip_arp_out(struct uip_driver_s *dev) * overwrite the IP packet with an ARP request. */ - memset(BUF->ethhdr.dest.addr, 0xff, IFHWADDRLEN); - memset(BUF->dhwaddr.addr, 0x00, IFHWADDRLEN); - memcpy(BUF->ethhdr.src.addr, dev->d_mac.addr, IFHWADDRLEN); - memcpy(BUF->shwaddr.addr, dev->d_mac.addr, IFHWADDRLEN); + memset(BUF->ah_ethhdr.dest.addr, 0xff, IFHWADDRLEN); + memset(BUF->ah_dhwaddr.addr, 0x00, IFHWADDRLEN); + memcpy(BUF->ah_ethhdr.src.addr, dev->d_mac.addr, IFHWADDRLEN); + memcpy(BUF->ah_shwaddr.addr, dev->d_mac.addr, IFHWADDRLEN); - uip_ipaddr_copy(BUF->dipaddr, ipaddr); - uip_ipaddr_copy(BUF->sipaddr, dev->d_ipaddr); - BUF->opcode = HTONS(ARP_REQUEST); /* ARP request. */ - BUF->hwtype = HTONS(ARP_HWTYPE_ETH); - BUF->protocol = HTONS(UIP_ETHTYPE_IP); - BUF->hwlen = IFHWADDRLEN; - BUF->protolen = 4; - BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP); + uiphdr_ipaddr_copy(BUF->ah_dipaddr, &ipaddr); + uiphdr_ipaddr_copy(BUF->ah_sipaddr, &dev->d_ipaddr); + BUF->ah_opcode = HTONS(ARP_REQUEST); /* ARP request. */ + BUF->ah_hwtype = HTONS(ARP_HWTYPE_ETH); + BUF->ah_protocol = HTONS(UIP_ETHTYPE_IP); + BUF->ah_hwlen = IFHWADDRLEN; + BUF->ah_protolen = 4; + BUF->ah_ethhdr.type = HTONS(UIP_ETHTYPE_ARP); dev->d_appdata = &dev->d_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN]; @@ -413,11 +455,11 @@ void uip_arp_out(struct uip_driver_s *dev) /* Build an ethernet header. */ - memcpy(IPBUF->ethhdr.dest.addr, tabptr->ethaddr.addr, IFHWADDRLEN); + memcpy(IPBUF->eh_ethhdr.dest.addr, tabptr->at_ethaddr.addr, IFHWADDRLEN); } - memcpy(IPBUF->ethhdr.src.addr, dev->d_mac.addr, IFHWADDRLEN); + memcpy(IPBUF->eh_ethhdr.src.addr, dev->d_mac.addr, IFHWADDRLEN); - IPBUF->ethhdr.type = HTONS(UIP_ETHTYPE_IP); + IPBUF->eh_ethhdr.type = HTONS(UIP_ETHTYPE_IP); dev->d_len += sizeof(struct uip_eth_hdr); } |