* reworking the network stack
@ 2010-06-04 9:54 Sascha Hauer
2010-06-04 9:54 ` [PATCH 01/13] net: remove need for eth_halt/eth_open Sascha Hauer
` (12 more replies)
0 siblings, 13 replies; 18+ messages in thread
From: Sascha Hauer @ 2010-06-04 9:54 UTC (permalink / raw)
To: barebox
Hi all,
The following series reimplements the network stack. There are not
many uservisible changes (hopefully) other than that the new stack
is smaller in binary size.
As a bonus we get netconsole support at the end of this series.
Sascha
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 01/13] net: remove need for eth_halt/eth_open
2010-06-04 9:54 reworking the network stack Sascha Hauer
@ 2010-06-04 9:54 ` Sascha Hauer
2010-06-04 9:54 ` [PATCH 02/13] net: Implement a new network stack Sascha Hauer
` (11 subsequent siblings)
12 siblings, 0 replies; 18+ messages in thread
From: Sascha Hauer @ 2010-06-04 9:54 UTC (permalink / raw)
To: barebox
We used to eth_open/eth_halt the network devices during NetLoopInit
which is called whenever the user enters a network command.
Change this behaviour so that the current network device gets opened
when making it the current one.
With this change it's always possible to send packages and we are able
to implement a new network stack in the next step.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
commands/net.c | 20 ++++++++++++--------
include/net.h | 1 +
net/eth.c | 56 ++++++++++++++++++++++++++++++++++++--------------------
net/net.c | 21 +++++++++++++--------
net/ping.c | 1 -
5 files changed, 62 insertions(+), 37 deletions(-)
diff --git a/commands/net.c b/commands/net.c
index 815a566..949963f 100644
--- a/commands/net.c
+++ b/commands/net.c
@@ -39,12 +39,16 @@ void netboot_update_env(void)
{
struct eth_device *eth_current = eth_get_current();
char tmp[22];
+ IPaddr_t net_gateway_ip = NetOurGatewayIP;
+ IPaddr_t net_ip = NetOurIP;
+ IPaddr_t net_server_ip = NetServerIP;
+ IPaddr_t netmask = NetOurSubnetMask;
- if (NetOurGatewayIP)
- dev_set_param_ip(ð_current->dev, "gateway", NetOurGatewayIP);
+ if (net_gateway_ip)
+ dev_set_param_ip(ð_current->dev, "gateway", net_gateway_ip);
- if (NetOurSubnetMask)
- dev_set_param_ip(ð_current->dev, "netmask", NetOurSubnetMask);
+ if (netmask)
+ dev_set_param_ip(ð_current->dev, "netmask", netmask);
if (NetOurHostName[0])
@@ -53,11 +57,11 @@ void netboot_update_env(void)
if (NetOurRootPath[0])
setenv ("rootpath", NetOurRootPath);
- if (NetOurIP)
- dev_set_param_ip(ð_current->dev, "ipaddr", NetOurIP);
+ if (net_ip)
+ dev_set_param_ip(ð_current->dev, "ipaddr", net_ip);
- if (NetServerIP)
- dev_set_param_ip(ð_current->dev, "serverip", NetServerIP);
+ if (net_server_ip)
+ dev_set_param_ip(ð_current->dev, "serverip", net_server_ip);
if (NetOurDNSIP) {
ip_to_string (NetOurDNSIP, tmp);
diff --git a/include/net.h b/include/net.h
index 7353c8f..de78293 100644
--- a/include/net.h
+++ b/include/net.h
@@ -57,6 +57,7 @@ struct device_d;
struct eth_device {
int iobase;
int state;
+ int active;
int (*init) (struct eth_device*);
diff --git a/net/eth.c b/net/eth.c
index 7570198..fc16233 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -36,7 +36,13 @@ static LIST_HEAD(netdev_list);
void eth_set_current(struct eth_device *eth)
{
+ if (eth_current && eth_current->active) {
+ eth_current->halt(eth_current);
+ eth_current->active = 0;
+ }
+
eth_current = eth;
+ net_update_env();
}
struct eth_device * eth_get_current(void)
@@ -57,37 +63,37 @@ struct eth_device *eth_get_byname(char *ethname)
return NULL;
}
-int eth_open(void)
-{
- if (!eth_current)
- return -ENODEV;
-
- return eth_current->open(eth_current);
-}
-
-void eth_halt(void)
-{
- if (!eth_current)
- return;
-
- eth_current->halt(eth_current);
-
- eth_current->state = ETH_STATE_PASSIVE;
-}
-
int eth_send(void *packet, int length)
{
+ int ret;
+
if (!eth_current)
return -ENODEV;
+ if (!eth_current->active) {
+ ret = eth_current->open(eth_current);
+ if (ret)
+ return ret;
+ eth_current->active = 1;
+ }
+
return eth_current->send(eth_current, packet, length);
}
int eth_rx(void)
{
+ int ret;
+
if (!eth_current)
return -ENODEV;
+ if (!eth_current->active) {
+ ret = eth_current->open(eth_current);
+ if (ret)
+ return ret;
+ eth_current->active = 1;
+ }
+
return eth_current->recv(eth_current);
}
@@ -104,11 +110,15 @@ static int eth_set_ethaddr(struct device_d *dev, struct param_d *param, const ch
edev->set_ethaddr(edev, ethaddr);
+ if (edev == eth_current)
+ net_update_env();
+
return 0;
}
static int eth_set_ipaddr(struct device_d *dev, struct param_d *param, const char *val)
{
+ struct eth_device *edev = dev->type_data;
IPaddr_t ip;
if (string_to_ip(val, &ip))
@@ -117,6 +127,9 @@ static int eth_set_ipaddr(struct device_d *dev, struct param_d *param, const cha
free(param->value);
param->value = strdup(val);
+ if (edev == eth_current)
+ net_update_env();
+
return 0;
}
@@ -157,7 +170,7 @@ int eth_register(struct eth_device *edev)
if (edev->get_ethaddr(edev, ethaddr) == 0) {
ethaddr_to_string(ethaddr, ethaddr_str);
- printf("got MAC address from EEPROM: %s\n",ethaddr_str);
+ printf("got MAC address from EEPROM: %s\n",ðaddr_str);
dev_set_param(dev, "ethaddr", ethaddr_str);
}
@@ -180,9 +193,12 @@ void eth_unregister(struct eth_device *edev)
if (edev->param_serverip.value)
free(edev->param_serverip.value);
- if (eth_current == edev)
+ if (eth_current == edev) {
+ eth_current->halt(eth_current);
eth_current = NULL;
+ }
list_del(&edev->list);
}
+
diff --git a/net/net.c b/net/net.c
index 4554d49..28943a0 100644
--- a/net/net.c
+++ b/net/net.c
@@ -228,9 +228,6 @@ int NetLoopInit(proto_t protocol)
NetArpWaitTxPacket -= (ulong)NetArpWaitTxPacket % PKTALIGN;
NetArpWaitTxPacketSize = 0;
- if (eth_open() < 0)
- return -1;
-
string_to_ethaddr(dev_get_param(ð_get_current()->dev, "ethaddr"),
NetOurEther);
@@ -243,8 +240,6 @@ int NetLoopInit(proto_t protocol)
NetServerIP = dev_get_param_ip(ð_current->dev, "serverip");
ret = net_check_prereq(protocol);
- if (ret)
- eth_halt();
return ret;
}
@@ -281,7 +276,6 @@ int NetLoop(void)
* Abort if ctrl-c was pressed.
*/
if (ctrlc()) {
- eth_halt();
puts ("\nAbort\n");
return -1;
}
@@ -315,11 +309,9 @@ int NetLoop(void)
sprintf(buf, "0x%lx", NetBootFileXferSize);
setenv("filesize", buf);
}
- eth_halt();
return NetBootFileXferSize;
case NETLOOP_FAIL:
- eth_halt();
return -1;
}
}
@@ -959,3 +951,16 @@ void ethaddr_to_string(const unsigned char *enetaddr, char *str)
enetaddr[4], enetaddr[5]);
}
+void net_update_env(void)
+{
+ struct eth_device *edev = eth_get_current();
+
+ NetOurIP = dev_get_param_ip(&edev->dev, "ipaddr");
+ NetServerIP = dev_get_param_ip(&edev->dev, "serverip");
+ NetOurGatewayIP = dev_get_param_ip(&edev->dev, "gateway");
+ NetOurSubnetMask = dev_get_param_ip(&edev->dev, "netmask");
+
+ string_to_ethaddr(dev_get_param(&edev->dev, "ethaddr"),
+ NetOurEther);
+}
+
diff --git a/net/ping.c b/net/ping.c
index 1bc481a..7e21fe4 100644
--- a/net/ping.c
+++ b/net/ping.c
@@ -62,7 +62,6 @@ static int PingSend(void)
static void
PingTimeout (void)
{
- eth_halt();
NetState = NETLOOP_FAIL; /* we did not get the reply */
}
--
1.7.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 02/13] net: Implement a new network stack
2010-06-04 9:54 reworking the network stack Sascha Hauer
2010-06-04 9:54 ` [PATCH 01/13] net: remove need for eth_halt/eth_open Sascha Hauer
@ 2010-06-04 9:54 ` Sascha Hauer
2010-06-04 9:54 ` [PATCH 03/13] remove unused sntp.h Sascha Hauer
` (10 subsequent siblings)
12 siblings, 0 replies; 18+ messages in thread
From: Sascha Hauer @ 2010-06-04 9:54 UTC (permalink / raw)
To: barebox
The old network stack has some bad limitations:
- network commands are required to call NetLoop() which only returns when
the network layer wants to. Instead we now use a net_poll() function which
returns after handling one packet (or immediately if no packet is
available).
- There can be only one packet handler which makes it impossible to handle
multiple connections
- CamelCaseMakesItHardToRead
The new network stack is implemented as a parallel universe. Currently all
commands still use the old stack. They are converted in subsequent patches.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
include/net.h | 339 +++++++++++++++++++++++++++++++++++++-
net/net.c | 521 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 854 insertions(+), 6 deletions(-)
diff --git a/include/net.h b/include/net.h
index de78293..f588a3d 100644
--- a/include/net.h
+++ b/include/net.h
@@ -15,6 +15,7 @@
#include <driver.h>
#include <linux/types.h>
#include <param.h>
+#include <malloc.h>
#include <asm/byteorder.h> /* for nton* / ntoh* stuff */
@@ -186,8 +187,6 @@ typedef struct
uchar ar_data[0];
} ARP_t;
-#define ARP_HDR_SIZE (8+20) /* Size assuming ethernet */
-
/*
* ICMP stuff (just enough to handle (host) redirect messages)
*/
@@ -199,7 +198,7 @@ typedef struct
#define ICMP_REDIR_NET 0 /* Redirect Net */
#define ICMP_REDIR_HOST 1 /* Redirect Host */
-typedef struct icmphdr {
+typedef struct {
uchar type;
uchar code;
ushort checksum;
@@ -415,4 +414,338 @@ void eth_set_current(struct eth_device *eth);
struct eth_device *eth_get_current(void);
struct eth_device *eth_get_byname(char *name);
+/*
+ * Ethernet header
+ */
+struct ethernet {
+ uint8_t et_dest[6]; /* Destination node */
+ uint8_t et_src[6]; /* Source node */
+ uint16_t et_protlen; /* Protocol or length */
+} __attribute__ ((packed));
+
+#define ETHER_HDR_SIZE 14 /* Ethernet header size */
+
+#define PROT_IP 0x0800 /* IP protocol */
+#define PROT_ARP 0x0806 /* IP ARP protocol */
+#define PROT_RARP 0x8035 /* IP ARP protocol */
+#define PROT_VLAN 0x8100 /* IEEE 802.1q protocol */
+
+#define IPPROTO_ICMP 1 /* Internet Control Message Protocol */
+#define IPPROTO_UDP 17 /* User Datagram Protocol */
+
+/*
+ * Internet Protocol (IP) header.
+ */
+struct iphdr {
+ uint8_t hl_v;
+ uint8_t tos;
+ uint16_t tot_len;
+ uint16_t id;
+ uint16_t frag_off;
+ uint8_t ttl;
+ uint8_t protocol;
+ uint16_t check;
+ uint32_t saddr;
+ uint32_t daddr;
+ /* The options start here. */
+} __attribute__ ((packed));
+
+struct udphdr {
+ uint16_t uh_sport; /* source port */
+ uint16_t uh_dport; /* destination port */
+ uint16_t uh_ulen; /* udp length */
+ uint16_t uh_sum; /* udp checksum */
+} __attribute__ ((packed));
+
+/*
+ * Address Resolution Protocol (ARP) header.
+ */
+struct arprequest
+{
+ uint16_t ar_hrd; /* Format of hardware address */
+#define ARP_ETHER 1 /* Ethernet hardware address */
+ uint16_t ar_pro; /* Format of protocol address */
+ uint8_t ar_hln; /* Length of hardware address */
+ uint8_t ar_pln; /* Length of protocol address */
+ uint16_t ar_op; /* Operation */
+#define ARPOP_REQUEST 1 /* Request to resolve address */
+#define ARPOP_REPLY 2 /* Response to previous request */
+
+#define RARPOP_REQUEST 3 /* Request to resolve address */
+#define RARPOP_REPLY 4 /* Response to previous request */
+
+ /*
+ * The remaining fields are variable in size, according to
+ * the sizes above, and are defined as appropriate for
+ * specific hardware/protocol combinations.
+ */
+ uint8_t ar_data[0];
+} __attribute__ ((packed));
+
+#define ARP_HDR_SIZE (8 + 20) /* Size assuming ethernet */
+
+/*
+ * ICMP stuff (just enough to handle (host) redirect messages)
+ */
+#define ICMP_ECHO_REPLY 0 /* Echo reply */
+#define ICMP_REDIRECT 5 /* Redirect (change route) */
+#define ICMP_ECHO_REQUEST 8 /* Echo request */
+
+/* Codes for REDIRECT. */
+#define ICMP_REDIR_NET 0 /* Redirect Net */
+#define ICMP_REDIR_HOST 1 /* Redirect Host */
+
+struct icmphdr {
+ uint8_t type;
+ uint8_t code;
+ uint16_t checksum;
+ union {
+ struct {
+ uint16_t id;
+ uint16_t sequence;
+ } echo;
+ uint32_t gateway;
+ struct {
+ uint16_t __unused;
+ uint16_t mtu;
+ } frag;
+ } un;
+} __attribute__ ((packed));
+
+
+/*
+ * Maximum packet size; used to allocate packet storage.
+ * TFTP packets can be 524 bytes + IP header + ethernet header.
+ * Lets be conservative, and go for 38 * 16. (Must also be
+ * a multiple of 32 bytes).
+ */
+#define PKTSIZE 1518
+
+/**********************************************************************/
+/*
+ * Globals.
+ *
+ * Note:
+ *
+ * All variables of type IPaddr_t are stored in NETWORK byte order
+ * (big endian).
+ */
+
+extern unsigned char *NetRxPackets[PKTBUFSRX];/* Receive packets */
+
+void net_set_ip(IPaddr_t ip);
+void net_set_serverip(IPaddr_t ip);
+void net_set_netmask(IPaddr_t ip);
+void net_set_gateway(IPaddr_t ip);
+void net_set_dnsip(IPaddr_t ip);
+IPaddr_t net_get_ip(void);
+IPaddr_t net_get_serverip(void);
+
+/* Do the work */
+void net_poll(void);
+
+static inline struct iphdr *net_eth_to_iphdr(char *pkt)
+{
+ return (struct iphdr *)(pkt + ETHER_HDR_SIZE);
+}
+
+static inline struct udphdr *net_eth_to_udphdr(char *pkt)
+{
+ return (struct udphdr *)(net_eth_to_iphdr(pkt) + 1);
+}
+
+static inline struct icmphdr *net_eth_to_icmphdr(char *pkt)
+{
+ return (struct icmphdr *)(net_eth_to_iphdr(pkt) + 1);
+}
+
+static inline char *net_eth_to_icmp_payload(char *pkt)
+{
+ return (char *)(net_eth_to_icmphdr(pkt) + 1);
+}
+
+static inline char *net_eth_to_udp_payload(char *pkt)
+{
+ return (char *)(net_eth_to_udphdr(pkt) + 1);
+}
+
+static inline int net_eth_to_udplen(char *pkt)
+{
+ struct udphdr *udp = net_eth_to_udphdr(pkt);
+ return ntohs(udp->uh_ulen) - 8;
+}
+
+int net_checksum_ok(unsigned char *, int); /* Return true if cksum OK */
+uint16_t net_checksum(unsigned char *, int); /* Calculate the checksum */
+
+void NetReceive(unsigned char *, int);
+
+/* Print an IP address on the console */
+void print_IPaddr (IPaddr_t);
+
+/*
+ * The following functions are a bit ugly, but necessary to deal with
+ * alignment restrictions on ARM.
+ *
+ * We're using inline functions, which had the smallest memory
+ * footprint in our tests.
+ */
+/* return IP *in network byteorder* */
+static inline IPaddr_t net_read_ip(void *from)
+{
+ IPaddr_t ip;
+ memcpy((void*)&ip, from, sizeof(ip));
+ return ip;
+}
+
+/* return uint32 *in network byteorder* */
+static inline uint32_t net_read_uint32(uint32_t *from)
+{
+ ulong l;
+ memcpy((void*)&l, (void*)from, sizeof(l));
+ return l;
+}
+
+/* write IP *in network byteorder* */
+static inline void net_write_ip(void *to, IPaddr_t ip)
+{
+ memcpy(to, (void*)&ip, sizeof(ip));
+}
+
+/* copy IP */
+static inline void net_copy_ip(void *to, void *from)
+{
+ memcpy(to, from, sizeof(IPaddr_t));
+}
+
+/* copy ulong */
+static inline void net_copy_uint32(uint32_t *to, uint32_t *from)
+{
+ memcpy(to, from, sizeof(uint32_t));
+}
+
+/* Convert an IP address to a string */
+char *ip_to_string (IPaddr_t x, char *s);
+
+/* Convert a string to ip address */
+int string_to_ip(const char *s, IPaddr_t *ip);
+
+int string_to_ethaddr(const char *str, char *enetaddr);
+void ethaddr_to_string(const unsigned char *enetaddr, char *str);
+
+/**
+ * is_zero_ether_addr - Determine if give Ethernet address is all zeros.
+ * @addr: Pointer to a six-byte array containing the Ethernet address
+ *
+ * Return true if the address is all zeroes.
+ */
+static inline int is_zero_ether_addr(const u8 *addr)
+{
+ return !(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]);
+}
+
+/**
+ * is_multicast_ether_addr - Determine if the Ethernet address is a multicast.
+ * @addr: Pointer to a six-byte array containing the Ethernet address
+ *
+ * Return true if the address is a multicast address.
+ * By definition the broadcast address is also a multicast address.
+ */
+static inline int is_multicast_ether_addr(const u8 *addr)
+{
+ return (0x01 & addr[0]);
+}
+
+/**
+ * is_local_ether_addr - Determine if the Ethernet address is locally-assigned one (IEEE 802).
+ * @addr: Pointer to a six-byte array containing the Ethernet address
+ *
+ * Return true if the address is a local address.
+ */
+static inline int is_local_ether_addr(const u8 *addr)
+{
+ return (0x02 & addr[0]);
+}
+
+/**
+ * is_broadcast_ether_addr - Determine if the Ethernet address is broadcast
+ * @addr: Pointer to a six-byte array containing the Ethernet address
+ *
+ * Return true if the address is the broadcast address.
+ */
+static inline int is_broadcast_ether_addr(const u8 *addr)
+{
+ return (addr[0] & addr[1] & addr[2] & addr[3] & addr[4] & addr[5]) == 0xff;
+}
+
+/**
+ * is_valid_ether_addr - Determine if the given Ethernet address is valid
+ * @addr: Pointer to a six-byte array containing the Ethernet address
+ *
+ * Check that the Ethernet address (MAC) is not 00:00:00:00:00:00, is not
+ * a multicast address, and is not FF:FF:FF:FF:FF:FF.
+ *
+ * Return true if the address is valid.
+ */
+static inline int is_valid_ether_addr(const u8 *addr)
+{
+ /* FF:FF:FF:FF:FF:FF is a multicast address so we don't need to
+ * explicitly check for it here. */
+ return !is_multicast_ether_addr(addr) && !is_zero_ether_addr(addr);
+}
+
+typedef void rx_handler_f(char *packet, unsigned int len);
+
+void eth_set_current(struct eth_device *eth);
+struct eth_device *eth_get_current(void);
+struct eth_device *eth_get_byname(char *name);
+void net_update_env(void);
+
+/**
+ * net_receive - Pass a received packet from an ethernet driver to the protocol stack
+ * @pkt: Pointer to the packet
+ * @len: length of the packet
+ *
+ * Return 0 if the packet is successfully handled. Can be ignored
+ */
+int net_receive(unsigned char *pkt, int len);
+
+struct net_connection {
+ struct ethernet *et;
+ struct iphdr *ip;
+ struct udphdr *udp;
+ struct icmphdr *icmp;
+ unsigned char *packet;
+ struct list_head list;
+ rx_handler_f *handler;
+ int proto;
+};
+
+static inline char *net_alloc_packet(void)
+{
+ return memalign(32, PKTSIZE);
+}
+
+struct net_connection *net_udp_new(IPaddr_t dest, uint16_t dport,
+ rx_handler_f *handler);
+
+struct net_connection *net_icmp_new(IPaddr_t dest, rx_handler_f *handler);
+
+void net_unregister(struct net_connection *con);
+
+static inline int net_udp_bind(struct net_connection *con, int sport)
+{
+ con->udp->uh_sport = ntohs(sport);
+ return 0;
+}
+
+static inline unsigned char *net_udp_get_payload(struct net_connection *con)
+{
+ return con->packet + sizeof(struct ethernet) + sizeof(struct iphdr) +
+ sizeof(struct udphdr);
+}
+
+int net_udp_send(struct net_connection *con, int len);
+int net_icmp_send(struct net_connection *con, int len);
+
#endif /* __NET_H__ */
diff --git a/net/net.c b/net/net.c
index 28943a0..6569b6f 100644
--- a/net/net.c
+++ b/net/net.c
@@ -77,7 +77,9 @@
#include <net.h>
#include <driver.h>
#include <errno.h>
+#include <init.h>
#include <linux/ctype.h>
+#include <linux/err.h>
#include "tftp.h"
#include "rarp.h"
#include "nfs.h"
@@ -407,6 +409,9 @@ NetReceive(uchar * inpkt, int len)
pr_debug("packet received\n");
+ if (!net_receive(inpkt, len))
+ return;
+
NetRxPkt = inpkt;
NetRxPktLen = len;
et = (Ethernet_t *)inpkt;
@@ -582,7 +587,8 @@ NetReceive(uchar * inpkt, int len)
NetCopyIP(&NetServerIP, &arp->ar_data[ 6]);
memcpy (NetServerEther, &arp->ar_data[ 0], 6);
- (*packetHandler)(0,0,0,0);
+ if (packetHandler)
+ (*packetHandler)(0,0,0,0);
}
break;
@@ -649,7 +655,8 @@ NetReceive(uchar * inpkt, int len)
* IP header OK. Pass the packet to the current handler.
*/
/* XXX point to ip packet */
- (*packetHandler)((uchar *)ip, 0, 0, 0);
+ if (packetHandler)
+ (*packetHandler)((uchar *)ip, 0, 0, 0);
return;
#endif
default:
@@ -701,7 +708,8 @@ NetReceive(uchar * inpkt, int len)
/*
* IP header OK. Pass the packet to the current handler.
*/
- (*packetHandler)((uchar *)ip +IP_HDR_SIZE,
+ if (packetHandler)
+ (*packetHandler)((uchar *)ip +IP_HDR_SIZE,
ntohs(ip->udp_dst),
ntohs(ip->udp_src),
ntohs(ip->udp_len) - 8);
@@ -951,10 +959,29 @@ void ethaddr_to_string(const unsigned char *enetaddr, char *str)
enetaddr[4], enetaddr[5]);
}
+static IPaddr_t net_netmask; /* Our subnet mask (0=unknown) */
+static IPaddr_t net_gateway; /* Our gateways IP address */
+static IPaddr_t net_dns_server; /* Our DNS IP address */
+
+static unsigned char net_ether[6]; /* Our ethernet address */
+static IPaddr_t net_ip; /* Our IP addr (0 = unknown) */
+static IPaddr_t net_serverip; /* Our IP addr (0 = unknown) */
+
+unsigned char *NetRxPackets[PKTBUFSRX]; /* Receive packets */
+static unsigned int net_ip_id;
+
void net_update_env(void)
{
struct eth_device *edev = eth_get_current();
+ net_ip = dev_get_param_ip(&edev->dev, "ipaddr");
+ net_serverip = dev_get_param_ip(&edev->dev, "serverip");
+ net_gateway = dev_get_param_ip(&edev->dev, "gateway");
+ net_netmask = dev_get_param_ip(&edev->dev, "netmask");
+
+ string_to_ethaddr(dev_get_param(&edev->dev, "ethaddr"),
+ net_ether);
+
NetOurIP = dev_get_param_ip(&edev->dev, "ipaddr");
NetServerIP = dev_get_param_ip(&edev->dev, "serverip");
NetOurGatewayIP = dev_get_param_ip(&edev->dev, "gateway");
@@ -964,3 +991,491 @@ void net_update_env(void)
NetOurEther);
}
+int net_checksum_ok(unsigned char *ptr, int len)
+{
+ return net_checksum(ptr, len) + 1;
+}
+
+uint16_t net_checksum(unsigned char *ptr, int len)
+{
+ uint32_t xsum = 0;
+ uint16_t *p = (uint16_t *)ptr;
+
+ if (len & 1)
+ ptr[len] = 0;
+
+ len = (len + 1) >> 1;
+
+ while (len-- > 0)
+ xsum += *p++;
+
+ xsum = (xsum & 0xffff) + (xsum >> 16);
+ xsum = (xsum & 0xffff) + (xsum >> 16);
+ return xsum & 0xffff;
+}
+
+static unsigned char *arp_ether;
+static IPaddr_t arp_wait_ip;
+
+static void arp_handler(struct arprequest *arp)
+{
+ IPaddr_t tmp;
+
+ /* are we waiting for a reply */
+ if (!arp_wait_ip)
+ return;
+
+ tmp = net_read_ip(&arp->ar_data[6]);
+
+ /* matched waiting packet's address */
+ if (tmp == arp_wait_ip) {
+ /* save address for later use */
+ memcpy(arp_ether, &arp->ar_data[0], 6);
+
+ /* no arp request pending now */
+ arp_wait_ip = 0;
+ }
+}
+
+int arp_request(IPaddr_t dest, unsigned char *ether)
+{
+ char *pkt;
+ struct arprequest *arp;
+ uint64_t arp_start;
+ static char *arp_packet;
+ struct ethernet *et;
+
+ if (!arp_packet) {
+ arp_packet = net_alloc_packet();
+ if (!arp_packet)
+ return -ENOMEM;
+ }
+
+ pkt = arp_packet;
+ et = (struct ethernet *)arp_packet;
+
+ arp_wait_ip = dest;
+
+ pr_debug("ARP broadcast\n");
+
+ memset(et->et_dest, 0xff, 6);
+ memcpy(et->et_src, net_ether, 6);
+ et->et_protlen = htons(PROT_ARP);
+
+ arp = (struct arprequest *)(pkt + ETHER_HDR_SIZE);
+
+ arp->ar_hrd = htons(ARP_ETHER);
+ arp->ar_pro = htons(PROT_IP);
+ arp->ar_hln = 6;
+ arp->ar_pln = 4;
+ arp->ar_op = htons(ARPOP_REQUEST);
+
+ memcpy(arp->ar_data, net_ether, 6); /* source ET addr */
+ net_write_ip(arp->ar_data + 6, net_ip); /* source IP addr */
+ memset(arp->ar_data + 10, 0, 6); /* dest ET addr = 0 */
+
+ if ((dest & net_netmask) != (net_ip & net_netmask)) {
+ if (!net_gateway)
+ arp_wait_ip = dest;
+ else
+ arp_wait_ip = net_gateway;
+ } else {
+ arp_wait_ip = dest;
+ }
+
+ net_write_ip(arp->ar_data + 16, arp_wait_ip);
+
+ arp_ether = ether;
+
+ eth_send(arp_packet, ETHER_HDR_SIZE + ARP_HDR_SIZE);
+ arp_start = get_time_ns();
+
+ while (arp_wait_ip) {
+ if (ctrlc())
+ return -EINTR;
+
+ if (is_timeout(arp_start, 3 * SECOND)) {
+ printf("T ");
+ arp_start = get_time_ns();
+ eth_send(arp_packet, ETHER_HDR_SIZE + ARP_HDR_SIZE);
+ }
+
+ net_poll();
+ }
+
+ pr_debug("Got ARP REPLY, set server/gtwy eth addr (%02x:%02x:%02x:%02x:%02x:%02x)\n",
+ ether[0], ether[1],
+ ether[2], ether[3],
+ ether[4], ether[5]);
+ return 0;
+}
+
+void net_poll(void)
+{
+ eth_rx();
+}
+
+static uint16_t net_udp_new_localport(void)
+{
+ static uint16_t localport;
+
+ localport++;
+
+ if (localport < 1024)
+ localport = 1024;
+
+ return localport;
+}
+
+IPaddr_t net_get_serverip(void)
+{
+ return net_serverip;
+}
+
+void net_set_serverip(IPaddr_t ip)
+{
+ struct eth_device *edev = eth_get_current();
+
+ net_serverip = ip;
+ dev_set_param_ip(&edev->dev, "serverip", net_serverip);
+}
+
+void net_set_ip(IPaddr_t ip)
+{
+ struct eth_device *edev = eth_get_current();
+
+ net_ip = ip;
+ dev_set_param_ip(&edev->dev, "ipaddr", net_ip);
+}
+
+IPaddr_t net_get_ip(void)
+{
+ return net_ip;
+}
+
+void net_set_netmask(IPaddr_t nm)
+{
+ struct eth_device *edev = eth_get_current();
+
+ net_netmask = nm;
+ dev_set_param_ip(&edev->dev, "netmask", net_netmask);
+}
+
+void net_set_gateway(IPaddr_t gw)
+{
+ struct eth_device *edev = eth_get_current();
+
+ net_gateway = gw;
+ dev_set_param_ip(&edev->dev, "gateway", net_gateway);
+}
+
+void net_set_dnsip(IPaddr_t dns)
+{
+ net_dns_server = dns;
+}
+
+static LIST_HEAD(connection_list);
+
+static struct net_connection *net_new(IPaddr_t dest, rx_handler_f *handler)
+{
+ struct net_connection *con;
+ int ret;
+
+ if (!is_valid_ether_addr(net_ether))
+ return ERR_PTR(-ENETDOWN);
+
+ /* If we don't have an ip only broadcast is allowed */
+ if (!net_ip && dest != 0xffffffff)
+ return ERR_PTR(-ENETDOWN);
+
+ con = xzalloc(sizeof(*con));
+ con->packet = memalign(32, PKTSIZE);
+ memset(con->packet, 0, PKTSIZE);
+
+ con->et = (struct ethernet *)con->packet;
+ con->ip = (struct iphdr *)(con->packet + ETHER_HDR_SIZE);
+ con->udp = (struct udphdr *)(con->packet + ETHER_HDR_SIZE + sizeof(struct iphdr));
+ con->icmp = (struct icmphdr *)(con->packet + ETHER_HDR_SIZE + sizeof(struct iphdr));
+ con->handler = handler;
+
+ if (dest == 0xffffffff) {
+ memset(con->et->et_dest, 0xff, 6);
+ } else {
+ ret = arp_request(dest, con->et->et_dest);
+ if (ret)
+ goto out;
+ }
+
+ con->et->et_protlen = htons(PROT_IP);
+ memcpy(con->et->et_src, net_ether, 6);
+
+ con->ip->hl_v = 0x45;
+ con->ip->tos = 0;
+ con->ip->frag_off = htons(0x4000); /* No fragmentation */;
+ con->ip->ttl = 255;
+ net_copy_ip(&con->ip->daddr, &dest);
+ net_copy_ip(&con->ip->saddr, &net_ip);
+
+ list_add_tail(&con->list, &connection_list);
+
+ return con;
+out:
+ free(con->packet);
+ free(con);
+ return ERR_PTR(ret);
+}
+
+struct net_connection *net_udp_new(IPaddr_t dest, uint16_t dport,
+ rx_handler_f *handler)
+{
+ struct net_connection *con = net_new(dest, handler);
+
+ if (IS_ERR(con))
+ return con;
+
+ con->proto = IPPROTO_UDP;
+ con->udp->uh_dport = htons(dport);
+ con->udp->uh_sport = htons(net_udp_new_localport());
+ con->ip->protocol = IPPROTO_UDP;
+
+ return con;
+}
+
+struct net_connection *net_icmp_new(IPaddr_t dest, rx_handler_f *handler)
+{
+ struct net_connection *con = net_new(dest, handler);
+
+ if (IS_ERR(con))
+ return con;
+
+ con->proto = IPPROTO_ICMP;
+ con->ip->protocol = IPPROTO_ICMP;
+
+ return con;
+}
+
+void net_unregister(struct net_connection *con)
+{
+ list_del(&con->list);
+ free(con->packet);
+ free(con);
+}
+
+int net_ip_send(struct net_connection *con, int len)
+{
+ con->ip->tot_len = htons(sizeof(struct iphdr) + len);
+ con->ip->id = htons(net_ip_id++);;
+ con->ip->check = 0;
+ con->ip->check = ~net_checksum((unsigned char *)con->ip, sizeof(struct iphdr));
+
+ eth_send(con->packet, ETHER_HDR_SIZE + sizeof(struct iphdr) + len);
+
+ return 0;
+}
+
+int net_udp_send(struct net_connection *con, int len)
+{
+ con->udp->uh_ulen = htons(len + 8);
+ con->udp->uh_sum = 0;
+
+ return net_ip_send(con, sizeof(struct udphdr) + len);
+}
+
+int net_icmp_send(struct net_connection *con, int len)
+{
+ con->icmp->checksum = ~net_checksum((unsigned char *)con->icmp,
+ sizeof(struct icmphdr) + len);
+
+ return net_ip_send(con, sizeof(struct icmphdr) + len);
+}
+
+static int net_answer_arp(unsigned char *pkt, int len)
+{
+ struct arprequest *arp = (struct arprequest *)(pkt + ETHER_HDR_SIZE);
+ struct ethernet *et = (struct ethernet *)pkt;
+ unsigned char *packet;
+
+ debug("%s\n", __func__);
+
+ memcpy (et->et_dest, et->et_src, 6);
+ memcpy (et->et_src, net_ether, 6);
+
+ et->et_protlen = htons(PROT_ARP);
+ arp->ar_op = htons(ARPOP_REPLY);
+ memcpy(&arp->ar_data[10], &arp->ar_data[0], 6);
+ net_copy_ip(&arp->ar_data[16], &arp->ar_data[6]);
+ memcpy(&arp->ar_data[0], net_ether, 6);
+ net_copy_ip(&arp->ar_data[6], &net_ip);
+
+ packet = net_alloc_packet();
+ if (!packet)
+ return 0;
+ memcpy(packet, pkt, ETHER_HDR_SIZE + ARP_HDR_SIZE);
+ eth_send(packet, ETHER_HDR_SIZE + ARP_HDR_SIZE);
+ free(packet);
+
+ return 0;
+}
+
+static void net_bad_packet(unsigned char *pkt, int len)
+{
+#ifdef DEBUG
+ /*
+ * We received a bad packet. for now just dump it.
+ * We could add more sophisticated debugging here
+ */
+ memory_display(pkt, 0, len, 1);
+#endif
+}
+
+static int net_handle_arp(unsigned char *pkt, int len)
+{
+ struct arprequest *arp;
+
+ debug("%s: got arp\n", __func__);
+
+ /*
+ * We have to deal with two types of ARP packets:
+ * - REQUEST packets will be answered by sending our
+ * IP address - if we know it.
+ * - REPLY packets are expected only after we asked
+ * for the TFTP server's or the gateway's ethernet
+ * address; so if we receive such a packet, we set
+ * the server ethernet address
+ */
+ arp = (struct arprequest *)(pkt + ETHER_HDR_SIZE);
+ if (len < ARP_HDR_SIZE)
+ goto bad;
+ if (ntohs(arp->ar_hrd) != ARP_ETHER)
+ goto bad;
+ if (ntohs(arp->ar_pro) != PROT_IP)
+ goto bad;
+ if (arp->ar_hln != 6)
+ goto bad;
+ if (arp->ar_pln != 4)
+ goto bad;
+ if (net_ip == 0)
+ return 0;
+ if (net_read_ip(&arp->ar_data[16]) != net_ip)
+ return 0;
+
+ switch (ntohs(arp->ar_op)) {
+ case ARPOP_REQUEST:
+ return net_answer_arp(pkt, len);
+ case ARPOP_REPLY:
+ arp_handler(arp);
+ return 1;
+ default:
+ pr_debug("Unexpected ARP opcode 0x%x\n", ntohs(arp->ar_op));
+ return -EINVAL;
+ }
+
+ return 0;
+
+bad:
+ net_bad_packet(pkt, len);
+ return -EINVAL;
+}
+
+static int net_handle_udp(unsigned char *pkt, int len)
+{
+ struct iphdr *ip = (struct iphdr *)(pkt + ETHER_HDR_SIZE);
+ struct net_connection *con;
+ struct udphdr *udp;
+ int port;
+
+ udp = (struct udphdr *)(ip + 1);
+ port = ntohs(udp->uh_dport);
+ list_for_each_entry(con, &connection_list, list) {
+ if (con->proto == IPPROTO_UDP && port == ntohs(con->udp->uh_sport)) {
+ con->handler(pkt, len);
+ return 0;
+ }
+ }
+ return -EINVAL;
+}
+
+static int net_handle_icmp(unsigned char *pkt, int len)
+{
+ struct net_connection *con;
+
+ debug("%s\n", __func__);
+
+ list_for_each_entry(con, &connection_list, list) {
+ if (con->proto == IPPROTO_ICMP) {
+ con->handler(pkt, len);
+ return 0;
+ }
+ }
+ return 0;
+}
+
+static int net_handle_ip(unsigned char *pkt, int len)
+{
+ struct iphdr *ip = (struct iphdr *)(pkt + ETHER_HDR_SIZE);
+ IPaddr_t tmp;
+
+ debug("%s\n", __func__);
+
+ if (len < sizeof(struct ethernet) + sizeof(struct iphdr) ||
+ len < ETHER_HDR_SIZE + ntohs(ip->tot_len)) {
+ debug("%s: bad len\n", __func__);
+ goto bad;
+ }
+
+ if ((ip->hl_v & 0xf0) != 0x40)
+ goto bad;
+
+ if (ip->frag_off & htons(0x1fff)) /* Can't deal w/ fragments */
+ goto bad;
+ if (!net_checksum_ok((unsigned char *)ip, sizeof(struct iphdr)))
+ goto bad;
+
+ tmp = net_read_ip(&ip->daddr);
+ if (net_ip && tmp != net_ip && tmp != 0xffffffff)
+ return 0;
+
+ switch (ip->protocol) {
+ case IPPROTO_ICMP:
+ return net_handle_icmp(pkt, len);
+ case IPPROTO_UDP:
+ return net_handle_udp(pkt, len);
+ }
+
+ return 0;
+bad:
+ net_bad_packet(pkt, len);
+ return 0;
+}
+
+int net_receive(unsigned char *pkt, int len)
+{
+ struct ethernet *et = (struct ethernet *)pkt;
+ int et_protlen = ntohs(et->et_protlen);
+
+ if (len < ETHER_HDR_SIZE)
+ return 0;
+
+ switch (et_protlen) {
+ case PROT_ARP:
+ return net_handle_arp(pkt, len);
+ case PROT_IP:
+ return net_handle_ip(pkt, len);
+ default:
+ debug("%s: got unknown protocol type: %d\n", __func__, et_protlen);
+ return 1;
+ }
+}
+
+static int net_init(void)
+{
+ int i;
+
+ for (i = 0; i < PKTBUFSRX; i++)
+ NetRxPackets[i] = memalign(32, PKTSIZE);
+
+ return 0;
+}
+
+postcore_initcall(net_init);
+
--
1.7.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 03/13] remove unused sntp.h
2010-06-04 9:54 reworking the network stack Sascha Hauer
2010-06-04 9:54 ` [PATCH 01/13] net: remove need for eth_halt/eth_open Sascha Hauer
2010-06-04 9:54 ` [PATCH 02/13] net: Implement a new network stack Sascha Hauer
@ 2010-06-04 9:54 ` Sascha Hauer
2010-06-04 9:55 ` [PATCH 04/13] implement dhcp using new network stack Sascha Hauer
` (9 subsequent siblings)
12 siblings, 0 replies; 18+ messages in thread
From: Sascha Hauer @ 2010-06-04 9:54 UTC (permalink / raw)
To: barebox
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
net/sntp.h | 61 ------------------------------------------------------------
1 files changed, 0 insertions(+), 61 deletions(-)
delete mode 100644 net/sntp.h
diff --git a/net/sntp.h b/net/sntp.h
deleted file mode 100644
index 8a097bf..0000000
--- a/net/sntp.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * (C) Masami Komiya <mkomiya@sonare.it> 2005
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2, or (at
- * your option) any later version.
- */
-
-#ifndef __SNTP_H__
-#define __SNTP_H__
-
-#define NTP_SERVICE_PORT 123
-#define SNTP_PACKET_LEN 48
-
-
-/* Leap Indicator */
-#define NTP_LI_NOLEAP 0x0
-#define NTP_LI_61SECS 0x1
-#define NTP_LI_59SECS 0x2
-#define NTP_LI_ALARM 0x3
-
-/* Version */
-
-#define NTP_VERSION 4
-
-/* Mode */
-#define NTP_MODE_RESERVED 0
-#define NTP_MODE_SYMACTIVE 1 /* Symmetric Active */
-#define NTP_MODE_SYMPASSIVE 2 /* Symmetric Passive */
-#define NTP_MODE_CLIENT 3
-#define NTP_MODE_SERVER 4
-#define NTP_MODE_BROADCAST 5
-#define NTP_MODE_NTPCTRL 6 /* Reserved for NTP control message */
-#define NTP_MODE_PRIVATE 7 /* Reserved for private use */
-
-struct sntp_pkt_t {
-#if __LITTLE_ENDIAN
- uchar mode:3;
- uchar vn:3;
- uchar li:2;
-#else
- uchar li:2;
- uchar vn:3;
- uchar mode:3;
-#endif
- uchar stratum;
- uchar poll;
- uchar precision;
- uint root_delay;
- uint root_dispersion;
- uint reference_id;
- unsigned long long reference_timestamp;
- unsigned long long originate_timestamp;
- unsigned long long receive_timestamp;
- unsigned long long transmit_timestamp;
-};
-
-extern void SntpStart (void); /* Begin SNTP */
-
-#endif /* __SNTP_H__ */
--
1.7.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 04/13] implement dhcp using new network stack
2010-06-04 9:54 reworking the network stack Sascha Hauer
` (2 preceding siblings ...)
2010-06-04 9:54 ` [PATCH 03/13] remove unused sntp.h Sascha Hauer
@ 2010-06-04 9:55 ` Sascha Hauer
2010-06-04 9:55 ` [PATCH 05/13] implement tftp " Sascha Hauer
` (8 subsequent siblings)
12 siblings, 0 replies; 18+ messages in thread
From: Sascha Hauer @ 2010-06-04 9:55 UTC (permalink / raw)
To: barebox
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
net/dhcp.c | 484 ++++++++++++++++++++++--------------------------------------
1 files changed, 173 insertions(+), 311 deletions(-)
diff --git a/net/dhcp.c b/net/dhcp.c
index f27a696..bedfb6e 100644
--- a/net/dhcp.c
+++ b/net/dhcp.c
@@ -14,64 +14,44 @@
#include <clock.h>
#include <net.h>
#include <libbb.h>
-#include "tftp.h"
-#include "nfs.h"
+#include <errno.h>
+#include <linux/err.h>
#define OPT_SIZE 312 /* Minimum DHCP Options size per RFC2131 - results in 576 byte pkt */
-typedef struct
-{
- uchar bp_op; /* Operation */
-# define OP_BOOTREQUEST 1
-# define OP_BOOTREPLY 2
- uchar bp_htype; /* Hardware type */
-# define HWT_ETHER 1
- uchar bp_hlen; /* Hardware address length */
-# define HWL_ETHER 6
- uchar bp_hops; /* Hop count (gateway thing) */
- ulong bp_id; /* Transaction ID */
- ushort bp_secs; /* Seconds since boot */
- ushort bp_spare1; /* Alignment */
+struct bootp {
+ uint8_t bp_op; /* Operation */
+#define OP_BOOTREQUEST 1
+#define OP_BOOTREPLY 2
+ uint8_t bp_htype; /* Hardware type */
+#define HWT_ETHER 1
+ uint8_t bp_hlen; /* Hardware address length */
+#define HWL_ETHER 6
+ uint8_t bp_hops; /* Hop count (gateway thing) */
+ uint32_t bp_id; /* Transaction ID */
+ uint16_t bp_secs; /* Seconds since boot */
+ uint16_t bp_spare1; /* Alignment */
IPaddr_t bp_ciaddr; /* Client IP address */
IPaddr_t bp_yiaddr; /* Your (client) IP address */
IPaddr_t bp_siaddr; /* Server IP address */
IPaddr_t bp_giaddr; /* Gateway IP address */
- uchar bp_chaddr[16]; /* Client hardware address */
+ uint8_t bp_chaddr[16]; /* Client hardware address */
char bp_sname[64]; /* Server host name */
char bp_file[128]; /* Boot file name */
- char bp_vend[OPT_SIZE]; /* Vendor information */
-} Bootp_t;
-
-#define BOOTP_HDR_SIZE sizeof (Bootp_t)
-#define BOOTP_SIZE (ETHER_HDR_SIZE + IP_HDR_SIZE + BOOTP_HDR_SIZE)
-
-/**********************************************************************/
-/*
- * Global functions and variables.
- */
-
-/* bootp.c */
-extern ulong BootpID; /* ID of cur BOOTP request */
-extern char BootFile[128]; /* Boot file name */
-#ifdef CONFIG_BOOTP_RANDOM_DELAY
-ulong seed1, seed2; /* seed for random BOOTP delay */
-#endif
-
-
-/* Send a BOOTP request */
-extern void BootpRequest (void);
-
-/****************** DHCP Support *********************/
+ char bp_vend[0]; /* Vendor information */
+};
/* DHCP States */
-typedef enum { INIT,
- INIT_REBOOT,
- REBOOTING,
- SELECTING,
- REQUESTING,
- REBINDING,
- BOUND,
- RENEWING } dhcp_state_t;
+typedef enum {
+ INIT,
+ INIT_REBOOT,
+ REBOOTING,
+ SELECTING,
+ REQUESTING,
+ REBINDING,
+ BOUND,
+ RENEWING,
+} dhcp_state_t;
#define DHCP_DISCOVER 1
#define DHCP_OFFER 2
@@ -81,44 +61,27 @@ typedef enum { INIT,
#define DHCP_NAK 6
#define DHCP_RELEASE 7
-#define SELECT_TIMEOUT 3 /* Seconds to wait for offers */
-
-/**********************************************************************/
-
#define BOOTP_VENDOR_MAGIC 0x63825363 /* RFC1048 Magic Cookie */
-#define TIMEOUT 5 /* Seconds before trying BOOTP again */
-#ifndef CONFIG_NET_RETRY_COUNT
-# define TIMEOUT_COUNT 5 /* # of timeouts before giving up */
-#else
-# define TIMEOUT_COUNT (CONFIG_NET_RETRY_COUNT)
-#endif
-
#define PORT_BOOTPS 67 /* BOOTP server UDP port */
#define PORT_BOOTPC 68 /* BOOTP client UDP port */
-#ifndef CONFIG_DHCP_MIN_EXT_LEN /* minimal length of extension list */
-#define CONFIG_DHCP_MIN_EXT_LEN 64
-#endif
-
-ulong BootpID;
-#ifdef CONFIG_BOOTP_RANDOM_DELAY
-ulong seed1, seed2;
-#endif
+#define DHCP_MIN_EXT_LEN 64 /* minimal length of extension list */
-dhcp_state_t dhcp_state = INIT;
-unsigned long dhcp_leasetime = 0;
-IPaddr_t NetDHCPServerIP = 0;
-static void DhcpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len);
+static uint32_t Bootp_id;
+static dhcp_state_t dhcp_state;
+static uint32_t dhcp_leasetime;
+static IPaddr_t net_dhcp_server_ip;
+static uint64_t dhcp_start;
-static int BootpCheckPkt(uchar *pkt, unsigned dest, unsigned src, unsigned len)
+static int bootp_check_packet(unsigned char *pkt, unsigned src, unsigned len)
{
- Bootp_t *bp = (Bootp_t *) pkt;
+ struct bootp *bp = (struct bootp *) pkt;
int retval = 0;
- if (dest != PORT_BOOTPC || src != PORT_BOOTPS)
+ if (src != PORT_BOOTPS)
retval = -1;
- else if (len < sizeof (Bootp_t) - OPT_SIZE)
+ else if (len < sizeof(struct bootp))
retval = -2;
else if (bp->bp_op != OP_BOOTREQUEST &&
bp->bp_op != OP_BOOTREPLY &&
@@ -131,11 +94,11 @@ static int BootpCheckPkt(uchar *pkt, unsigned dest, unsigned src, unsigned len)
retval = -4;
else if (bp->bp_hlen != HWL_ETHER)
retval = -5;
- else if (NetReadLong((ulong*)&bp->bp_id) != BootpID) {
+ else if (net_read_uint32(&bp->bp_id) != Bootp_id) {
retval = -6;
}
- debug ("Filtering pkt = %d\n", retval);
+ debug("Filtering pkt = %d\n", retval);
return retval;
}
@@ -143,64 +106,31 @@ static int BootpCheckPkt(uchar *pkt, unsigned dest, unsigned src, unsigned len)
/*
* Copy parameters of interest from BOOTP_REPLY/DHCP_OFFER packet
*/
-static void BootpCopyNetParams(Bootp_t *bp)
+static void bootp_copy_net_params(struct bootp *bp)
{
IPaddr_t tmp_ip;
- NetCopyIP(&NetOurIP, &bp->bp_yiaddr);
- NetCopyIP(&tmp_ip, &bp->bp_siaddr);
- if (tmp_ip != 0)
- NetCopyIP(&NetServerIP, &bp->bp_siaddr);
- memcpy (NetServerEther, ((Ethernet_t *)NetRxPkt)->et_src, 6);
- if (strlen(bp->bp_file) > 0)
- safe_strncpy (BootFile, bp->bp_file, sizeof(BootFile));
+ tmp_ip = net_read_ip(&bp->bp_yiaddr);
+ net_set_ip(tmp_ip);
- debug ("Bootfile: %s\n", BootFile);
-
- /* Propagate to environment:
- * don't delete exising entry when BOOTP / DHCP reply does
- * not contain a new value
- */
- if (*BootFile) {
- setenv ("bootfile", BootFile);
- }
-}
+ tmp_ip = net_read_ip(&bp->bp_siaddr);
+ if (tmp_ip != 0)
+ net_set_serverip(tmp_ip);
-static int truncate_sz (const char *name, int maxlen, int curlen)
-{
- if (curlen >= maxlen) {
- printf("*** WARNING: %s is too long (%d - max: %d) - truncated\n",
- name, curlen, maxlen);
- curlen = maxlen - 1;
- }
- return (curlen);
-}
+ if (strlen(bp->bp_file) > 0)
+ setenv("bootfile", bp->bp_file);
-/*
- * Timeout on BOOTP/DHCP request.
- */
-static void
-BootpTimeout(void)
-{
- NetSetTimeout (TIMEOUT * SECOND, BootpTimeout);
- BootpRequest ();
+ debug("bootfile: %s\n", bp->bp_file);
}
/*
- * Initialize BOOTP extension fields in the request.
+ * Initialize BOOTP extension fields in the request.
*/
-static int DhcpExtended (u8 * e, int message_type, IPaddr_t ServerID, IPaddr_t RequestedIP)
+static int dhcp_extended (u8 *e, int message_type, IPaddr_t ServerID, IPaddr_t RequestedIP)
{
u8 *start = e;
u8 *cnt;
-#ifdef CONFIG_BOOTP_VENDOREX
- u8 *x;
-#endif
-#ifdef CONFIG_BOOTP_SEND_HOSTNAME
- char *hostname;
-#endif
-
*e++ = 99; /* RFC1048 Magic Cookie */
*e++ = 130;
*e++ = 83;
@@ -236,175 +166,113 @@ static int DhcpExtended (u8 * e, int message_type, IPaddr_t ServerID, IPaddr_t R
*e++ = tmp >> 8;
*e++ = tmp & 0xff;
}
-#ifdef CONFIG_BOOTP_SEND_HOSTNAME
- if ((hostname = getenv ("hostname"))) {
- int hostnamelen = strlen (hostname);
-
- *e++ = 12; /* Hostname */
- *e++ = hostnamelen;
- memcpy (e, hostname, hostnamelen);
- e += hostnamelen;
- }
-#endif
*e++ = 55; /* Parameter Request List */
cnt = e++; /* Pointer to count of requested items */
*cnt = 0;
-#ifdef CONFIG_BOOTP_SUBNETMASK
*e++ = 1; /* Subnet Mask */
*cnt += 1;
-#endif
-#ifdef CONFIG_BOOTP_TIMEOFFSET
- *e++ = 2;
- *cnt += 1;
-#endif
-#ifdef CONFIG_BOOTP_GATEWAY
*e++ = 3; /* Router Option */
*cnt += 1;
-#endif
-#ifdef CONFIG_BOOTP_DNS
*e++ = 6; /* DNS Server(s) */
*cnt += 1;
-#endif
-#ifdef CONFIG_BOOTP_HOSTNAME
*e++ = 12; /* Hostname */
*cnt += 1;
-#endif
-#ifdef CONFIG_BOOTP_BOOTFILESIZE
- *e++ = 13; /* Boot File Size */
- *cnt += 1;
-#endif
-#ifdef CONFIG_BOOTP_BOOTPATH
*e++ = 17; /* Boot path */
*cnt += 1;
-#endif
-#ifdef CONFIG_BOOTP_NISDOMAIN
- *e++ = 40; /* NIS Domain name request */
- *cnt += 1;
-#endif
-#ifdef CONFIG_BOOTP_NTPSERVER
- *e++ = 42;
- *cnt += 1;
-#endif
*e++ = 255; /* End of the list */
/* Pad to minimal length */
-#ifdef CONFIG_DHCP_MIN_EXT_LEN
- while ((e - start) <= CONFIG_DHCP_MIN_EXT_LEN)
+ while ((e - start) <= DHCP_MIN_EXT_LEN)
*e++ = 0;
-#endif
return e - start;
}
-void
-BootpRequest (void)
+static struct net_connection *dhcp_con;
+
+static int bootp_request(void)
{
- uchar *pkt, *iphdr;
- Bootp_t *bp;
- int ext_len, pktlen, iplen;
+ struct bootp *bp;
+ int ext_len;
+ int ret;
+ unsigned char *payload = net_udp_get_payload(dhcp_con);
+ const char *bfile;
dhcp_state = INIT;
- printf("BOOTP broadcast\n");
- pkt = NetTxPacket;
- memset ((void*)pkt, 0, PKTSIZE);
+ debug("BOOTP broadcast\n");
- pkt += NetSetEther(pkt, NetBcastAddr, PROT_IP);
-
- /*
- * Next line results in incorrect packet size being transmitted, resulting
- * in errors in some DHCP servers, reporting missing bytes. Size must be
- * set in packet header after extension length has been determined.
- * C. Hallinan, DS4.COM, Inc.
- */
- /* NetSetIP(pkt, 0xFFFFFFFFL, PORT_BOOTPS, PORT_BOOTPC, sizeof (Bootp_t)); */
- iphdr = pkt; /* We need this later for NetSetIP() */
- pkt += IP_HDR_SIZE;
-
- bp = (Bootp_t *)pkt;
+ bp = (struct bootp *)payload;
bp->bp_op = OP_BOOTREQUEST;
bp->bp_htype = HWT_ETHER;
bp->bp_hlen = HWL_ETHER;
bp->bp_hops = 0;
bp->bp_secs = htons(get_time_ns() >> 30);
- NetWriteIP(&bp->bp_ciaddr, 0);
- NetWriteIP(&bp->bp_yiaddr, 0);
- NetWriteIP(&bp->bp_siaddr, 0);
- NetWriteIP(&bp->bp_giaddr, 0);
- memcpy (bp->bp_chaddr, NetOurEther, 6);
- safe_strncpy (bp->bp_file, BootFile, sizeof(bp->bp_file));
+ net_write_ip(&bp->bp_ciaddr, 0);
+ net_write_ip(&bp->bp_yiaddr, 0);
+ net_write_ip(&bp->bp_siaddr, 0);
+ net_write_ip(&bp->bp_giaddr, 0);
+ memcpy(bp->bp_chaddr, dhcp_con->et->et_src, 6);
- /* Request additional information from the BOOTP/DHCP server */
- ext_len = DhcpExtended((u8 *)bp->bp_vend, DHCP_DISCOVER, 0, 0);
+ bfile = getenv("bootfile");
+ if (bfile)
+ safe_strncpy (bp->bp_file, bfile, sizeof(bp->bp_file));
- /*
- * Bootp ID is the lower 4 bytes of our ethernet address
- * plus the current time in HZ.
- */
- BootpID = ((ulong)NetOurEther[2] << 24)
- | ((ulong)NetOurEther[3] << 16)
- | ((ulong)NetOurEther[4] << 8)
- | (ulong)NetOurEther[5];
- BootpID += (uint32_t)get_time_ns();
- BootpID = htonl(BootpID);
- NetCopyLong(&bp->bp_id, &BootpID);
+ /* Request additional information from the BOOTP/DHCP server */
+ ext_len = dhcp_extended((u8 *)bp->bp_vend, DHCP_DISCOVER, 0, 0);
- /*
- * Calculate proper packet lengths taking into account the
- * variable size of the options field
- */
- pktlen = BOOTP_SIZE - sizeof(bp->bp_vend) + ext_len;
- iplen = BOOTP_HDR_SIZE - sizeof(bp->bp_vend) + ext_len;
- NetSetIP(iphdr, 0xFFFFFFFFL, PORT_BOOTPS, PORT_BOOTPC, iplen);
- NetSetTimeout(SELECT_TIMEOUT * SECOND, BootpTimeout);
+ Bootp_id = (uint32_t)get_time_ns();
+ net_copy_uint32(&bp->bp_id, &Bootp_id);
dhcp_state = SELECTING;
- NetSetHandler(DhcpHandler);
- NetSendPacket(NetTxPacket, pktlen);
+
+ ret = net_udp_send(dhcp_con, sizeof(*bp) + ext_len);
+
+ return ret;
}
-static void DhcpOptionsProcess (uchar * popt, Bootp_t *bp)
+static void dhcp_options_process(unsigned char *popt, struct bootp *bp)
{
- uchar *end = popt + BOOTP_HDR_SIZE;
- int oplen, size;
+ unsigned char *end = popt + sizeof(*bp) + OPT_SIZE;
+ int oplen;
+ IPaddr_t ip;
+ char str[256];
while (popt < end && *popt != 0xff) {
oplen = *(popt + 1);
switch (*popt) {
case 1:
- NetCopyIP (&NetOurSubnetMask, (popt + 2));
+ ip = net_read_ip(popt + 2);
+ net_set_netmask(ip);
break;
case 3:
- NetCopyIP (&NetOurGatewayIP, (popt + 2));
+ ip = net_read_ip(popt + 2);
+ net_set_gateway(ip);
break;
case 6:
- NetCopyIP (&NetOurDNSIP, (popt + 2));
-#ifdef CONFIG_BOOTP_DNS2
- if (*(popt + 1) > 4) {
- NetCopyIP (&NetOurDNS2IP, (popt + 2 + 4));
- }
-#endif
+ ip = net_read_ip(popt + 2);
+ net_set_dnsip(ip);
break;
case 12:
- size = truncate_sz ("Host Name", sizeof (NetOurHostName), oplen);
- memcpy (&NetOurHostName, popt + 2, size);
- NetOurHostName[size] = 0;
+ memcpy(str, popt + 2, oplen);
+ str[oplen] = 0;
+ setenv("hostname", str);
break;
case 15: /* Ignore Domain Name Option */
break;
case 17:
- size = truncate_sz ("Root Path", sizeof (NetOurRootPath), oplen);
- memcpy (&NetOurRootPath, popt + 2, size);
- NetOurRootPath[size] = 0;
+ memcpy(str, popt + 2, oplen);
+ str[oplen] = 0;
+ setenv("rootpath", str);
break;
case 51:
- NetCopyLong (&dhcp_leasetime, (ulong *) (popt + 2));
+ net_copy_uint32 (&dhcp_leasetime, (uint32_t *)(popt + 2));
break;
case 53: /* Ignore Message Type Option */
break;
case 54:
- NetCopyIP (&NetDHCPServerIP, (popt + 2));
+ net_copy_ip(&net_dhcp_server_ip, (popt + 2));
break;
case 58: /* Ignore Renewal Time Option */
break;
@@ -419,10 +287,9 @@ static void DhcpOptionsProcess (uchar * popt, Bootp_t *bp)
* pass the bootp packet pointer into here as the
* second arg
*/
- size = truncate_sz ("Opt Boot File",
- sizeof(bp->bp_file),
- oplen);
- if (bp->bp_file[0] == '\0' && size > 0) {
+ memcpy(str, popt + 2, oplen);
+ str[oplen] = 0;
+ if (bp->bp_file[0] == '\0') {
/*
* only use vendor boot file if we didn't
* receive a boot file in the main non-vendor
@@ -434,8 +301,7 @@ static void DhcpOptionsProcess (uchar * popt, Bootp_t *bp)
*/
printf("*** WARNING: using vendor "
"optional boot file\n");
- memcpy(bp->bp_file, popt + 2, size);
- bp->bp_file[size] = '\0';
+ setenv("bootfile", str);
}
break;
default:
@@ -443,16 +309,16 @@ static void DhcpOptionsProcess (uchar * popt, Bootp_t *bp)
if (dhcp_vendorex_proc (popt))
break;
#endif
- printf ("*** Unhandled DHCP Option in OFFER/ACK: %d\n", *popt);
+ debug("*** Unhandled DHCP Option in OFFER/ACK: %d\n", *popt);
break;
}
popt += oplen + 2; /* Process next option */
}
}
-static int DhcpMessageType(unsigned char *popt)
+static int dhcp_message_type(unsigned char *popt)
{
- if (NetReadLong((ulong*)popt) != htonl(BOOTP_VENDOR_MAGIC))
+ if (net_read_uint32((uint32_t *)popt) != htonl(BOOTP_VENDOR_MAGIC))
return -1;
popt += 4;
@@ -464,76 +330,65 @@ static int DhcpMessageType(unsigned char *popt)
return -1;
}
-static void DhcpSendRequestPkt(Bootp_t *bp_offer)
+static void dhcp_send_request_packet(struct bootp *bp_offer)
{
- uchar *pkt, *iphdr;
- Bootp_t *bp;
- int pktlen, iplen, extlen;
+ struct bootp *bp;
+ int extlen;
IPaddr_t OfferedIP;
+ unsigned char *payload = net_udp_get_payload(dhcp_con);
- debug ("DhcpSendRequestPkt: Sending DHCPREQUEST\n");
- pkt = NetTxPacket;
- memset ((void*)pkt, 0, PKTSIZE);
-
- pkt += NetSetEther(pkt, NetBcastAddr, PROT_IP);
+ debug("%s: Sending DHCPREQUEST\n", __func__);
- iphdr = pkt; /* We'll need this later to set proper pkt size */
- pkt += IP_HDR_SIZE;
-
- bp = (Bootp_t *)pkt;
+ bp = (struct bootp *)payload;
bp->bp_op = OP_BOOTREQUEST;
bp->bp_htype = HWT_ETHER;
bp->bp_hlen = HWL_ETHER;
bp->bp_hops = 0;
/* FIXME what is this? */
// bp->bp_secs = htons(get_timer(0) / CFG_HZ);
- NetCopyIP(&bp->bp_ciaddr, &bp_offer->bp_ciaddr); /* both in network byte order */
- NetCopyIP(&bp->bp_yiaddr, &bp_offer->bp_yiaddr);
- NetCopyIP(&bp->bp_siaddr, &bp_offer->bp_siaddr);
+ net_copy_ip(&bp->bp_ciaddr, &bp_offer->bp_ciaddr); /* both in network byte order */
+ net_copy_ip(&bp->bp_yiaddr, &bp_offer->bp_yiaddr);
+ net_copy_ip(&bp->bp_siaddr, &bp_offer->bp_siaddr);
/*
* RFC3046 requires Relay Agents to discard packets with
* nonzero and offered giaddr
*/
- NetWriteIP(&bp->bp_giaddr, 0);
+ net_write_ip(&bp->bp_giaddr, 0);
- memcpy (bp->bp_chaddr, NetOurEther, 6);
+ memcpy(bp->bp_chaddr, dhcp_con->et->et_src, 6);
/*
* ID is the id of the OFFER packet
*/
- NetCopyLong(&bp->bp_id, &bp_offer->bp_id);
+ net_copy_uint32(&bp->bp_id, &bp_offer->bp_id);
/*
* Copy options from OFFER packet if present
*/
- NetCopyIP(&OfferedIP, &bp->bp_yiaddr);
- extlen = DhcpExtended((u8 *)bp->bp_vend, DHCP_REQUEST, NetDHCPServerIP, OfferedIP);
-
- pktlen = BOOTP_SIZE - sizeof(bp->bp_vend) + extlen;
- iplen = BOOTP_HDR_SIZE - sizeof(bp->bp_vend) + extlen;
- NetSetIP(iphdr, 0xFFFFFFFFL, PORT_BOOTPS, PORT_BOOTPC, iplen);
+ net_copy_ip(&OfferedIP, &bp->bp_yiaddr);
+ extlen = dhcp_extended((u8 *)bp->bp_vend, DHCP_REQUEST, net_dhcp_server_ip, OfferedIP);
- debug ("Transmitting DHCPREQUEST packet: len = %d\n", pktlen);
- NetSendPacket(NetTxPacket, pktlen);
+ debug("Transmitting DHCPREQUEST packet\n");
+ net_udp_send(dhcp_con, sizeof(*bp) + extlen);
}
/*
* Handle DHCP received packets.
*/
-static void
-DhcpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
+static void dhcp_handler(char *packet, unsigned int len)
{
- Bootp_t *bp = (Bootp_t *)pkt;
+ char *pkt = net_eth_to_udp_payload(packet);
+ struct udphdr *udp = net_eth_to_udphdr(packet);
+ struct bootp *bp = (struct bootp *)pkt;
- debug ("DHCPHandler: got packet: (src=%d, dst=%d, len=%d) state: %d\n",
- src, dest, len, dhcp_state);
+ len = net_eth_to_udplen(packet);
- if (BootpCheckPkt(pkt, dest, src, len)) /* Filter out pkts we don't want */
- return;
+ debug("DHCPHandler: got packet: (len=%d) state: %d\n",
+ len, dhcp_state);
- debug ("DHCPHandler: got DHCP packet: (src=%d, dst=%d, len=%d) state: %d\n",
- src, dest, len, dhcp_state);
+ if (bootp_check_packet(pkt, ntohs(udp->uh_sport), len)) /* Filter out pkts we don't want */
+ return;
switch (dhcp_state) {
case SELECTING:
@@ -543,69 +398,76 @@ DhcpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
* If filename is in format we recognize, assume it is a valid
* OFFER from a server we want.
*/
- debug ("DHCP: state=SELECTING bp_file: \"%s\"\n", bp->bp_file);
-#ifdef CFG_BOOTFILE_PREFIX
- if (strncmp(bp->bp_file,
- CFG_BOOTFILE_PREFIX,
- strlen(CFG_BOOTFILE_PREFIX)) == 0 ) {
-#endif /* CFG_BOOTFILE_PREFIX */
-
- debug ("TRANSITIONING TO REQUESTING STATE\n");
- dhcp_state = REQUESTING;
+ debug ("%s: state SELECTING, bp_file: \"%s\"\n", __func__, bp->bp_file);
+ dhcp_state = REQUESTING;
- if (NetReadLong((ulong*)&bp->bp_vend[0]) == htonl(BOOTP_VENDOR_MAGIC))
- DhcpOptionsProcess((u8 *)&bp->bp_vend[4], bp);
+ if (net_read_uint32((uint32_t *)&bp->bp_vend[0]) == htonl(BOOTP_VENDOR_MAGIC))
+ dhcp_options_process((u8 *)&bp->bp_vend[4], bp);
- BootpCopyNetParams(bp); /* Store net params from reply */
+ bootp_copy_net_params(bp); /* Store net params from reply */
- NetSetTimeout(TIMEOUT * SECOND, BootpTimeout);
- DhcpSendRequestPkt(bp);
-#ifdef CFG_BOOTFILE_PREFIX
- }
-#endif /* CFG_BOOTFILE_PREFIX */
+ dhcp_start = get_time_ns();
+ dhcp_send_request_packet(bp);
- return;
break;
case REQUESTING:
- debug ("DHCP State: REQUESTING\n");
+ debug ("%s: State REQUESTING\n", __func__);
- if ( DhcpMessageType((u8 *)bp->bp_vend) == DHCP_ACK ) {
- if (NetReadLong((ulong*)&bp->bp_vend[0]) == htonl(BOOTP_VENDOR_MAGIC))
- DhcpOptionsProcess((u8 *)&bp->bp_vend[4], bp);
- BootpCopyNetParams(bp); /* Store net params from reply */
+ if (dhcp_message_type((u8 *)bp->bp_vend) == DHCP_ACK ) {
+ if (net_read_uint32((uint32_t *)&bp->bp_vend[0]) == htonl(BOOTP_VENDOR_MAGIC))
+ dhcp_options_process((u8 *)&bp->bp_vend[4], bp);
+ bootp_copy_net_params(bp); /* Store net params from reply */
dhcp_state = BOUND;
puts ("DHCP client bound to address ");
- print_IPaddr(NetOurIP);
+ print_IPaddr(net_get_ip());
putchar('\n');
-
- NetState = NETLOOP_SUCCESS;
return;
}
break;
default:
- puts ("DHCP: INVALID STATE\n");
+ debug("%s: INVALID STATE\n", __func__);
break;
}
-
}
static int do_dhcp(struct command *cmdtp, int argc, char *argv[])
{
- int size;
+ int ret;
+
+ dhcp_con = net_udp_new(0xffffffff, PORT_BOOTPS, dhcp_handler);
+ if (IS_ERR(dhcp_con)) {
+ ret = PTR_ERR(dhcp_con);
+ goto out;
+ }
+
+ ret = net_udp_bind(dhcp_con, PORT_BOOTPC);
+ if (ret)
+ goto out;
- if (NetLoopInit(DHCP) < 0)
- return 1;
+ ret = bootp_request(); /* Basically same as BOOTP */
+ if (ret)
+ goto out;
- NetOurIP = 0;
- BootpRequest(); /* Basically same as BOOTP */
+ while (dhcp_state != BOUND) {
+ if (ctrlc())
+ break;
+ net_poll();
+ if (is_timeout(dhcp_start, 3 * SECOND)) {
+ dhcp_start = get_time_ns();
+ printf("T ");
+ ret = bootp_request();
+ if (ret)
+ goto out;
+ }
+ }
- if ((size = NetLoop()) < 0)
- return 1;
+out:
+ net_unregister(dhcp_con);
- /* NetLoop ok, update environment */
- netboot_update_env();
+ if (ret)
+ printf("dhcp failed: %s\n", strerror(-ret));
- return 0;
+ return ret ? 1 : 0;
}
BAREBOX_CMD_START(dhcp)
--
1.7.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 05/13] implement tftp using new network stack
2010-06-04 9:54 reworking the network stack Sascha Hauer
` (3 preceding siblings ...)
2010-06-04 9:55 ` [PATCH 04/13] implement dhcp using new network stack Sascha Hauer
@ 2010-06-04 9:55 ` Sascha Hauer
2010-06-04 9:55 ` [PATCH 06/13] implement ping " Sascha Hauer
` (7 subsequent siblings)
12 siblings, 0 replies; 18+ messages in thread
From: Sascha Hauer @ 2010-06-04 9:55 UTC (permalink / raw)
To: barebox
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
net/tftp.c | 253 ++++++++++++++++++++++++++++--------------------------------
1 files changed, 119 insertions(+), 134 deletions(-)
diff --git a/net/tftp.c b/net/tftp.c
index e8a8a3a..b0bc7c5 100644
--- a/net/tftp.c
+++ b/net/tftp.c
@@ -13,9 +13,9 @@
#include <errno.h>
#include <libgen.h>
#include <fcntl.h>
-#include "tftp.h"
+#include <linux/err.h>
-#define WELL_KNOWN_PORT 69 /* Well known TFTP port # */
+#define TFTP_PORT 69 /* Well known TFTP port # */
#define TIMEOUT 5 /* Seconds to timeout for a lost pkt */
# define TIMEOUT_COUNT 10 /* # of timeouts before giving up */
/* (for checking the image size) */
@@ -32,60 +32,45 @@
#define TFTP_OACK 6
-static int TftpServerPort; /* The UDP port at their end */
-static int TftpOurPort; /* The UDP port at our end */
-static ulong TftpBlock; /* packet sequence number */
-static ulong TftpLastBlock; /* last packet sequence number received */
-static ulong TftpBlockWrap; /* count of sequence number wraparounds */
-static ulong TftpBlockWrapOffset; /* memory offset due to wrapping */
-static int TftpState;
+static int tftp_server_port; /* The UDP port at their end */
+static unsigned int tftp_block; /* packet sequence number */
+static unsigned int tftp_last_block; /* last packet sequence number received */
+static unsigned int tftp_block_wrap; /* count of sequence number wraparounds */
+static unsigned int tftp_block_wrap_offset; /* memory offset due to wrapping */
+static int tftp_state;
+static uint64_t tftp_timer_start;
+static int tftp_err;
#define STATE_RRQ 1
#define STATE_DATA 2
#define STATE_OACK 3
+#define STATE_DONE 4
#define TFTP_BLOCK_SIZE 512 /* default TFTP block size */
-#define TFTP_SEQUENCE_SIZE ((ulong)(1<<16)) /* sequence number is 16 bit */
+#define TFTP_SEQUENCE_SIZE ((unsigned long)(1<<16)) /* sequence number is 16 bit */
static char *tftp_filename;
-
+static struct net_connection *tftp_con;
static int net_store_fd;
-static int store_block(unsigned block, uchar * src, unsigned len)
-{
- ulong offset = block * TFTP_BLOCK_SIZE + TftpBlockWrapOffset;
- ulong newsize = offset + len;
- int ret;
-
- ret = write(net_store_fd, src, len);
- if (ret < 0)
- return ret;
-
- if (NetBootFileXferSize < newsize)
- NetBootFileXferSize = newsize;
- return 0;
-}
-
-static void TftpSend(void)
+static int tftp_send(void)
{
- uchar *pkt;
- uchar *xp;
+ unsigned char *pkt;
+ unsigned char *xp;
int len = 0;
- ushort *s;
+ uint16_t *s;
+ unsigned char *packet = net_udp_get_payload(tftp_con);
+ int ret;
- /*
- * We will always be sending some sort of packet, so
- * cobble together the packet headers now.
- */
- pkt = NetTxPacket + NetEthHdrSize() + IP_HDR_SIZE;
+ pkt = packet;
- switch (TftpState) {
+ switch (tftp_state) {
case STATE_RRQ:
xp = pkt;
- s = (ushort *)pkt;
+ s = (uint16_t *)pkt;
*s++ = htons(TFTP_RRQ);
- pkt = (uchar *)s;
- pkt += sprintf((uchar *)pkt, "%s%coctet%ctimeout%c%d",
+ pkt = (unsigned char *)s;
+ pkt += sprintf((unsigned char *)pkt, "%s%coctet%ctimeout%c%d",
tftp_filename, 0, 0, 0, TIMEOUT) + 1;
len = pkt - xp;
break;
@@ -93,44 +78,36 @@ static void TftpSend(void)
case STATE_DATA:
case STATE_OACK:
xp = pkt;
- s = (ushort *)pkt;
+ s = (uint16_t *)pkt;
*s++ = htons(TFTP_ACK);
- *s++ = htons(TftpBlock);
- pkt = (uchar *)s;
+ *s++ = htons(tftp_block);
+ pkt = (unsigned char *)s;
len = pkt - xp;
break;
}
- NetSendUDPPacket(NetServerEther, NetServerIP, TftpServerPort,
- TftpOurPort, len);
-}
+ ret = net_udp_send(tftp_con, len);
-static void TftpTimeout(void)
-{
- puts("T ");
- NetSetTimeout(TIMEOUT * SECOND, TftpTimeout);
- TftpSend();
+ return ret;
}
-static void TftpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
+static void tftp_handler(char *packet, unsigned len)
{
- ushort proto;
- ushort *s;
-
- if (dest != TftpOurPort)
- return;
-
- if (TftpState != STATE_RRQ && src != TftpServerPort)
- return;
+ uint16_t proto;
+ uint16_t *s;
+ char *pkt = net_eth_to_udp_payload(packet);
+ struct udphdr *udp = net_eth_to_udphdr(packet);
+ int ret;
+ len = net_eth_to_udplen(packet);
if (len < 2)
return;
len -= 2;
/* warning: don't use increment (++) in ntohs() macros!! */
- s = (ushort *)pkt;
+ s = (uint16_t *)pkt;
proto = *s++;
- pkt = (uchar *)s;
+ pkt = (unsigned char *)s;
switch (ntohs(proto)) {
case TFTP_RRQ:
case TFTP_WRQ:
@@ -140,16 +117,17 @@ static void TftpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
break;
case TFTP_OACK:
- debug("Got OACK: %s %s\n", pkt, pkt+strlen(pkt)+1);
- TftpState = STATE_OACK;
- TftpServerPort = src;
- TftpSend(); /* Send ACK */
+ debug("Got OACK: %s %s\n", pkt, pkt + strlen(pkt) + 1);
+ tftp_state = STATE_OACK;
+ tftp_server_port = ntohs(udp->uh_sport);
+ tftp_con->udp->uh_dport = udp->uh_sport;
+ tftp_send(); /* Send ACK */
break;
case TFTP_DATA:
if (len < 2)
return;
len -= 2;
- TftpBlock = ntohs(*(ushort *)pkt);
+ tftp_block = ntohs(*(uint16_t *)pkt);
/*
* RFC1350 specifies that the first data packet will
@@ -157,49 +135,50 @@ static void TftpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
* number of 0 this means that there was a wrap
* around of the (16 bit) counter.
*/
- if (TftpBlock == 0) {
- TftpBlockWrap++;
- TftpBlockWrapOffset += TFTP_BLOCK_SIZE * TFTP_SEQUENCE_SIZE;
- printf ("\n\t %lu MB received\n\t ", TftpBlockWrapOffset>>20);
+ if (tftp_block == 0) {
+ tftp_block_wrap++;
+ tftp_block_wrap_offset += TFTP_BLOCK_SIZE * TFTP_SEQUENCE_SIZE;
} else {
- if (((TftpBlock - 1) % 10) == 0) {
+ if (((tftp_block - 1) % 10) == 0) {
putchar('#');
- } else if ((TftpBlock % (10 * HASHES_PER_LINE)) == 0) {
+ } else if ((tftp_block % (10 * HASHES_PER_LINE)) == 0) {
puts("\n\t ");
}
}
- if (TftpState == STATE_RRQ)
+ if (tftp_state == STATE_RRQ)
debug("Server did not acknowledge timeout option!\n");
- if (TftpState == STATE_RRQ || TftpState == STATE_OACK) {
+ if (tftp_state == STATE_RRQ || tftp_state == STATE_OACK) {
/* first block received */
- TftpState = STATE_DATA;
- TftpServerPort = src;
- TftpLastBlock = 0;
- TftpBlockWrap = 0;
- TftpBlockWrapOffset = 0;
-
- if (TftpBlock != 1) { /* Assertion */
- printf("\nTFTP error: "
- "First block is not block 1 (%ld)\n"
- "Starting again\n\n",
- TftpBlock);
- NetState = NETLOOP_FAIL;
+ tftp_state = STATE_DATA;
+ tftp_con->udp->uh_dport = udp->uh_sport;
+ tftp_server_port = ntohs(udp->uh_sport);
+ tftp_last_block = 0;
+ tftp_block_wrap = 0;
+ tftp_block_wrap_offset = 0;
+
+ if (tftp_block != 1) { /* Assertion */
+ printf("error: First block is not block 1 (%ld)\n",
+ tftp_block);
+ tftp_err = -EINVAL;
+ tftp_state = STATE_DONE;
break;
}
}
- if (TftpBlock == TftpLastBlock)
+ if (tftp_block == tftp_last_block)
/* Same block again; ignore it. */
break;
- TftpLastBlock = TftpBlock;
- NetSetTimeout(TIMEOUT * SECOND, TftpTimeout);
+ tftp_last_block = tftp_block;
+ tftp_timer_start = get_time_ns();
- if (store_block(TftpBlock - 1, pkt + 2, len) < 0) {
+ ret = write(net_store_fd, pkt + 2, len);
+ if (ret < 0) {
perror("write");
- NetState = NETLOOP_FAIL;
+ tftp_err = -errno;
+ tftp_state = STATE_DONE;
return;
}
@@ -207,58 +186,51 @@ static void TftpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
* Acknowledge the block just received, which will prompt
* the server for the next one.
*/
- TftpSend();
-
- if (len < TFTP_BLOCK_SIZE) {
- /*
- * We received the whole thing. Try to
- * run it.
- */
- puts("\ndone\n");
- NetState = NETLOOP_SUCCESS;
- }
+ tftp_send();
+
+ if (len < TFTP_BLOCK_SIZE)
+ tftp_state = STATE_DONE;
+
break;
case TFTP_ERROR:
- printf("\nTFTP error: '%s' (%d)\n",
- pkt + 2, ntohs(*(ushort *)pkt));
- NetState = NETLOOP_FAIL;
+ debug("\nTFTP error: '%s' (%d)\n",
+ pkt + 2, ntohs(*(uint16_t *)pkt));
+ switch (ntohs(*(uint16_t *)pkt)) {
+ case 1: tftp_err = -ENOENT; break;
+ case 2: tftp_err = -EACCES; break;
+ default: tftp_err = -EINVAL; break;
+ }
+ tftp_state = STATE_DONE;
break;
}
}
-void TftpStart(char *filename)
+static int tftp_start(char *filename)
{
- char ip1[16], ip2[16];
+ char ip1[16];
tftp_filename = filename;
- printf("TFTP from server %s; our IP address is %s\n"
- "\nFilename '%s'.\nLoading: *\b",
- ip_to_string(NetServerIP, ip1),
- ip_to_string(NetOurIP, ip2),
+ printf("TFTP from server %s; Filename: '%s'\nLoading: ",
+ ip_to_string(net_get_serverip(), ip1),
tftp_filename);
- NetSetTimeout(TIMEOUT * SECOND, TftpTimeout);
- NetSetHandler(TftpHandler);
+ tftp_timer_start = get_time_ns();
+ tftp_state = STATE_RRQ;
+ tftp_block = 0;
- TftpServerPort = WELL_KNOWN_PORT;
- TftpState = STATE_RRQ;
- /* Use a pseudo-random port */
- TftpOurPort = 1024 + ((unsigned int)get_time_ns() % 3072);
- TftpBlock = 0;
+ tftp_con = net_udp_new(net_get_serverip(), TFTP_PORT, tftp_handler);
+ if (IS_ERR(tftp_con))
+ return PTR_ERR(tftp_con);
- /* zero out server ether in case the server ip has changed */
- memset(NetServerEther, 0, 6);
-
- TftpSend();
+ return tftp_send();
}
static int do_tftpb(struct command *cmdtp, int argc, char *argv[])
{
- int rcode = 0;
- char *localfile;
- char *remotefile;
+ char *localfile;
+ char *remotefile;
if (argc < 2)
return COMMAND_ERROR_USAGE;
@@ -276,22 +248,35 @@ static int do_tftpb(struct command *cmdtp, int argc, char *argv[])
return 1;
}
- if (NetLoopInit(TFTP) < 0)
+ tftp_err = tftp_start(remotefile);
+ if (tftp_err)
goto out;
- TftpStart(remotefile);
-
- if (NetLoop() < 0) {
- rcode = 1;
- goto out;
+ while (tftp_state != STATE_DONE) {
+ if (ctrlc()) {
+ tftp_err = -EINTR;
+ break;
+ }
+ net_poll();
+ if (is_timeout(tftp_timer_start, SECOND)) {
+ tftp_timer_start = get_time_ns();
+ printf("T ");
+ tftp_send();
+ }
}
- /* NetLoop ok, update environment */
- netboot_update_env();
+ net_unregister(tftp_con);
-out:
close(net_store_fd);
- return rcode;
+out:
+ if (tftp_err) {
+ printf("\ntftp failed: %s\n", strerror(-tftp_err));
+ unlink(localfile);
+ }
+
+ printf("\n");
+
+ return tftp_err == 0 ? 0 : 1;
}
static const __maybe_unused char cmd_tftp_help[] =
--
1.7.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 06/13] implement ping using new network stack
2010-06-04 9:54 reworking the network stack Sascha Hauer
` (4 preceding siblings ...)
2010-06-04 9:55 ` [PATCH 05/13] implement tftp " Sascha Hauer
@ 2010-06-04 9:55 ` Sascha Hauer
2010-06-04 9:55 ` [PATCH 07/13] implement nfs " Sascha Hauer
` (6 subsequent siblings)
12 siblings, 0 replies; 18+ messages in thread
From: Sascha Hauer @ 2010-06-04 9:55 UTC (permalink / raw)
To: barebox
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
net/ping.c | 147 ++++++++++++++++++++++++++++++------------------------------
1 files changed, 74 insertions(+), 73 deletions(-)
diff --git a/net/ping.c b/net/ping.c
index 7e21fe4..0f9868e 100644
--- a/net/ping.c
+++ b/net/ping.c
@@ -2,102 +2,103 @@
#include <command.h>
#include <clock.h>
#include <net.h>
+#include <errno.h>
+#include <linux/err.h>
-static ushort PingSeqNo;
+static uint16_t ping_sequence_number;
-static IPaddr_t NetPingIP; /* the ip address to ping */
+static IPaddr_t net_ping_ip; /* the ip address to ping */
-static int PingSend(void)
-{
- static uchar mac[6];
- IP_t *ip;
- ushort *s;
- uchar *pkt;
-
- /* XXX always send arp request */
-
- memcpy(mac, NetEtherNullAddr, 6);
-
- pr_debug("sending ARP for %08lx\n", NetPingIP);
-
- NetArpWaitPacketIP = NetPingIP;
- NetArpWaitPacketMAC = mac;
-
- pkt = NetArpWaitTxPacket;
- pkt += NetSetEther(pkt, mac, PROT_IP);
-
- ip = (IP_t *)pkt;
-
- /*
- * Construct an IP and ICMP header. (need to set no fragment bit - XXX)
- */
- ip->ip_hl_v = 0x45; /* IP_HDR_SIZE / 4 (not including UDP) */
- ip->ip_tos = 0;
- ip->ip_len = htons(IP_HDR_SIZE_NO_UDP + 8);
- ip->ip_id = htons(NetIPID++);
- ip->ip_off = htons(0x4000); /* No fragmentation */
- ip->ip_ttl = 255;
- ip->ip_p = 0x01; /* ICMP */
- ip->ip_sum = 0;
- NetCopyIP((void*)&ip->ip_src, &NetOurIP); /* already in network byte order */
- NetCopyIP((void*)&ip->ip_dst, &NetPingIP); /* - "" - */
- ip->ip_sum = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2);
-
- s = &ip->udp_src; /* XXX ICMP starts here */
- s[0] = htons(0x0800); /* echo-request, code */
- s[1] = 0; /* checksum */
- s[2] = 0; /* identifier */
- s[3] = htons(PingSeqNo++); /* sequence number */
- s[1] = ~NetCksum((uchar *)s, 8/2);
-
- /* size of the waiting packet */
- NetArpWaitTxPacketSize = (pkt - NetArpWaitTxPacket) + IP_HDR_SIZE_NO_UDP + 8;
-
- /* and do the ARP request */
- NetArpWaitTimerStart = get_time_ns();
- ArpRequest();
- return 1; /* waiting */
-}
+#define PING_STATE_INIT 0
+#define PING_STATE_SUCCESS 1
+
+static int ping_state;
-static void
-PingTimeout (void)
+static struct net_connection *ping_con;
+
+static int ping_send(void)
{
- NetState = NETLOOP_FAIL; /* we did not get the reply */
+ unsigned char *payload;
+ struct icmphdr *icmp;
+ uint64_t ts;
+
+ icmp = ping_con->icmp;
+
+ icmp->type = ICMP_ECHO_REQUEST;
+ icmp->code = 0;
+ icmp->checksum = 0;
+ icmp->un.echo.id = 0;
+ icmp->un.echo.sequence = htons(ping_sequence_number);
+
+ ping_sequence_number++;
+
+ payload = (char *)(icmp + 1);
+ ts = get_time_ns();
+ memcpy(payload, &ts, sizeof(ts));
+ payload[8] = 0xab;
+ payload[9] = 0xcd;
+ return net_icmp_send(ping_con, 9);
}
-static void
-PingHandler (uchar * pkt, unsigned dest, unsigned src, unsigned len)
+void ping_handler(char *pkt, unsigned len)
{
IPaddr_t tmp;
- IP_t *ip = (IP_t *)pkt;
+ struct iphdr *ip = net_eth_to_iphdr(pkt);
- tmp = NetReadIP((void *)&ip->ip_src);
- if (tmp != NetPingIP)
+ tmp = net_read_ip((void *)&ip->saddr);
+ if (tmp != net_ping_ip)
return;
- NetState = NETLOOP_SUCCESS;
+ ping_state = PING_STATE_SUCCESS;
}
int do_ping(struct command *cmdtp, int argc, char *argv[])
{
- if (argc < 2 || string_to_ip(argv[1], &NetPingIP))
+ int ret;
+ uint64_t ping_start = 0;
+
+ if (argc < 2 || string_to_ip(argv[1], &net_ping_ip))
return COMMAND_ERROR_USAGE;
- if (NetLoopInit(PING) < 0)
- return 1;
+ ping_con = net_icmp_new(net_ping_ip, ping_handler);
+ if (IS_ERR(ping_con)) {
+ ret = PTR_ERR(ping_con);
+ goto out;
+ }
+
+ ping_start = get_time_ns();
+ ret = ping_send();
+ if (ret)
+ goto out_unreg;
+
+ ping_state = PING_STATE_INIT;
+ ping_sequence_number = 0;
+
+ while (ping_state == PING_STATE_INIT) {
+ if (ctrlc()) {
+ ret = -EINTR;
+ break;
+ }
- NetSetTimeout (10 * SECOND, PingTimeout);
- NetSetHandler (PingHandler);
- PingSend();
+ net_poll();
- if (NetLoop() < 0) {
- printf("ping failed; host %s is not alive\n", argv[1]);
- return 1;
+ if (is_timeout(ping_start, 10 * SECOND)) {
+ ping_start = get_time_ns();
+ ret = ping_send();
+ if (ret)
+ goto out_unreg;
+ }
}
- printf("host %s is alive\n", argv[1]);
+ if (!ret)
+ printf("host %s is alive\n", argv[1]);
- return 0;
+out_unreg:
+ net_unregister(ping_con);
+out:
+ if (ret)
+ printf("ping failed: %s\n", strerror(-ret));
+ return ping_state == PING_STATE_SUCCESS ? 0 : 1;
}
BAREBOX_CMD_START(ping)
--
1.7.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 07/13] implement nfs using new network stack
2010-06-04 9:54 reworking the network stack Sascha Hauer
` (5 preceding siblings ...)
2010-06-04 9:55 ` [PATCH 06/13] implement ping " Sascha Hauer
@ 2010-06-04 9:55 ` Sascha Hauer
2010-06-04 9:55 ` [PATCH 08/13] net: consider rarp support as outdated. Remove it Sascha Hauer
` (5 subsequent siblings)
12 siblings, 0 replies; 18+ messages in thread
From: Sascha Hauer @ 2010-06-04 9:55 UTC (permalink / raw)
To: barebox
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
net/nfs.c | 716 +++++++++++++++++++++++++++++-------------------------------
1 files changed, 346 insertions(+), 370 deletions(-)
diff --git a/net/nfs.c b/net/nfs.c
index 15f91ab..51df7a3 100644
--- a/net/nfs.c
+++ b/net/nfs.c
@@ -32,28 +32,111 @@
#include <libgen.h>
#include <fcntl.h>
#include <errno.h>
-#include "nfs.h"
-
-/*#define NFS_DEBUG*/
+#include <linux/err.h>
+
+#define SUNRPC_PORT 111
+
+#define PROG_PORTMAP 100000
+#define PROG_NFS 100003
+#define PROG_MOUNT 100005
+
+#define MSG_CALL 0
+#define MSG_REPLY 1
+
+#define PORTMAP_GETPORT 3
+
+#define MOUNT_ADDENTRY 1
+#define MOUNT_UMOUNTALL 4
+
+#define NFS_LOOKUP 4
+#define NFS_READLINK 5
+#define NFS_READ 6
+
+#define NFS_FHSIZE 32
+
+enum nfs_stat {
+ NFS_OK = 0,
+ NFSERR_PERM = 1,
+ NFSERR_NOENT = 2,
+ NFSERR_IO = 5,
+ NFSERR_NXIO = 6,
+ NFSERR_ACCES = 13,
+ NFSERR_EXIST = 17,
+ NFSERR_NODEV = 19,
+ NFSERR_NOTDIR = 20,
+ NFSERR_ISDIR = 21,
+ NFSERR_FBIG = 27,
+ NFSERR_NOSPC = 28,
+ NFSERR_ROFS = 30,
+ NFSERR_NAMETOOLONG=63,
+ NFSERR_NOTEMPTY = 66,
+ NFSERR_DQUOT = 69,
+ NFSERR_STALE = 70,
+ NFSERR_WFLUSH = 99,
+};
+
+/* Block size used for NFS read accesses. A RPC reply packet (including all
+ * headers) must fit within a single Ethernet frame to avoid fragmentation.
+ * Chosen to be a power of two, as most NFS servers are optimized for this. */
+#define NFS_READ_SIZE 1024
+
+struct rpc_call {
+ uint32_t id;
+ uint32_t type;
+ uint32_t rpcvers;
+ uint32_t prog;
+ uint32_t vers;
+ uint32_t proc;
+ uint32_t data[0];
+};
+
+struct rpc_reply {
+ uint32_t id;
+ uint32_t type;
+ uint32_t rstatus;
+ uint32_t verifier;
+ uint32_t v2;
+ uint32_t astatus;
+ uint32_t data[0];
+};
+
+struct rpc_t {
+ union {
+ struct {
+ uint32_t id;
+ uint32_t type;
+ uint32_t rpcvers;
+ uint32_t prog;
+ uint32_t vers;
+ uint32_t proc;
+ uint32_t data[1];
+ } call;
+ struct {
+ uint32_t id;
+ uint32_t type;
+ uint32_t rstatus;
+ uint32_t verifier;
+ uint32_t v2;
+ uint32_t astatus;
+ uint32_t data[19];
+ } reply;
+ } u;
+};
#define HASHES_PER_LINE 65 /* Number of "loading" hashes per line */
#define NFS_TIMEOUT 60
-static int fs_mounted = 0;
static unsigned long rpc_id = 0;
static int nfs_offset = -1;
-static int nfs_len;
+static uint64_t nfs_timer_start;
+static int nfs_err;
static char dirfh[NFS_FHSIZE]; /* file handle of directory */
static char filefh[NFS_FHSIZE]; /* file handle of kernel image */
-static int NfsDownloadState;
-static IPaddr_t NfsServerIP;
-static int NfsSrvMountPort;
-static int NfsSrvNfsPort;
-static int NfsOurPort;
-static int NfsTimeoutCount;
-static int NfsState;
+static int nfs_server_mount_port;
+static int nfs_server_nfs_port;
+static int nfs_state;
#define STATE_PRCLOOKUP_PROG_MOUNT_REQ 1
#define STATE_PRCLOOKUP_PROG_NFS_REQ 2
#define STATE_MOUNT_REQ 3
@@ -61,40 +144,22 @@ static int NfsState;
#define STATE_LOOKUP_REQ 5
#define STATE_READ_REQ 6
#define STATE_READLINK_REQ 7
+#define STATE_DONE 8
static char *nfs_filename;
static char *nfs_path;
static char nfs_path_buff[2048];
static int net_store_fd;
-
-static __inline__ int
-store_block (uchar * src, unsigned offset, unsigned len)
-{
- ulong newsize = offset + len;
- int ret;
-
- ret = write(net_store_fd, src, len);
- if (ret < 0)
- return ret;
-
- if (NetBootFileXferSize < (offset+len))
- NetBootFileXferSize = newsize;
-
- return 0;
-}
+static struct net_connection *nfs_con;
/**************************************************************************
RPC_ADD_CREDENTIALS - Add RPC authentication/verifier entries
**************************************************************************/
-static long *rpc_add_credentials (long *p)
+static uint32_t *rpc_add_credentials(uint32_t *p)
{
int hl;
- int hostnamelen;
- char hostname[256];
-
- strcpy (hostname, "");
- hostnamelen=strlen (hostname);
+ int hostnamelen = 0;
/* Here's the executive summary on authentication requirements of the
* various NFS server implementations: Linux accepts both AUTH_NONE
@@ -112,10 +177,12 @@ static long *rpc_add_credentials (long *p)
*p++ = htonl(hl+20); /* auth length */
*p++ = htonl(0); /* stamp */
*p++ = htonl(hostnamelen); /* hostname string */
- if (hostnamelen & 3) {
+
+ if (hostnamelen & 3)
*(p + hostnamelen / 4) = 0; /* add zero padding */
- }
- memcpy (p, hostname, hostnamelen);
+
+ /* memcpy(p, hostname, hostnamelen); */ /* empty hostname */
+
p += hl / 4;
*p++ = 0; /* uid */
*p++ = 0; /* gid */
@@ -131,46 +198,42 @@ static long *rpc_add_credentials (long *p)
/**************************************************************************
RPC_LOOKUP - Lookup RPC Port numbers
**************************************************************************/
-static void
-rpc_req (int rpc_prog, int rpc_proc, uint32_t *data, int datalen)
+static int rpc_req(int rpc_prog, int rpc_proc, uint32_t *data, int datalen)
{
- struct rpc_t pkt;
+ struct rpc_call pkt;
unsigned long id;
- uint32_t *p;
- int pktlen;
int sport;
+ int ret;
+ unsigned char *payload = net_udp_get_payload(nfs_con);
id = ++rpc_id;
- pkt.u.call.id = htonl(id);
- pkt.u.call.type = htonl(MSG_CALL);
- pkt.u.call.rpcvers = htonl(2); /* use RPC version 2 */
- pkt.u.call.prog = htonl(rpc_prog);
- pkt.u.call.vers = htonl(2); /* portmapper is version 2 */
- pkt.u.call.proc = htonl(rpc_proc);
- p = (uint32_t *)&(pkt.u.call.data);
-
- if (datalen)
- memcpy ((char *)p, (char *)data, datalen*sizeof(uint32_t));
-
- pktlen = (char *)p + datalen*sizeof(uint32_t) - (char *)&pkt;
+ pkt.id = htonl(id);
+ pkt.type = htonl(MSG_CALL);
+ pkt.rpcvers = htonl(2); /* use RPC version 2 */
+ pkt.prog = htonl(rpc_prog);
+ pkt.vers = htonl(2); /* portmapper is version 2 */
+ pkt.proc = htonl(rpc_proc);
- memcpy ((char *)NetTxPacket + NetEthHdrSize() + IP_HDR_SIZE, (char *)&pkt, pktlen);
+ memcpy(payload, &pkt, sizeof(pkt));
+ memcpy(payload + sizeof(pkt), data, datalen * sizeof(uint32_t));
if (rpc_prog == PROG_PORTMAP)
sport = SUNRPC_PORT;
else if (rpc_prog == PROG_MOUNT)
- sport = NfsSrvMountPort;
+ sport = nfs_server_mount_port;
else
- sport = NfsSrvNfsPort;
+ sport = nfs_server_nfs_port;
- NetSendUDPPacket (NetServerEther, NfsServerIP, sport, NfsOurPort, pktlen);
+ nfs_con->udp->uh_dport = htons(sport);
+ ret = net_udp_send(nfs_con, sizeof(pkt) + datalen * sizeof(uint32_t));
+
+ return ret;
}
/**************************************************************************
RPC_LOOKUP - Lookup RPC Port numbers
**************************************************************************/
-static void
-rpc_lookup_req (int prog, int ver)
+static void rpc_lookup_req(int prog, int ver)
{
uint32_t data[16];
@@ -181,14 +244,13 @@ rpc_lookup_req (int prog, int ver)
data[6] = htonl(17); /* IP_UDP */
data[7] = 0;
- rpc_req (PROG_PORTMAP, PORTMAP_GETPORT, data, 8);
+ rpc_req(PROG_PORTMAP, PORTMAP_GETPORT, data, 8);
}
/**************************************************************************
NFS_MOUNT - Mount an NFS Filesystem
**************************************************************************/
-static void
-nfs_mount_req (char *path)
+static void nfs_mount_req(char *path)
{
uint32_t data[1024];
uint32_t *p;
@@ -198,39 +260,38 @@ nfs_mount_req (char *path)
pathlen = strlen (path);
p = &(data[0]);
- p = (uint32_t *)rpc_add_credentials((long *)p);
+ p = rpc_add_credentials(p);
*p++ = htonl(pathlen);
- if (pathlen & 3) *(p + pathlen / 4) = 0;
+ if (pathlen & 3)
+ *(p + pathlen / 4) = 0;
memcpy (p, path, pathlen);
p += (pathlen + 3) / 4;
- len = (uint32_t *)p - (uint32_t *)&(data[0]);
+ len = p - &(data[0]);
- rpc_req (PROG_MOUNT, MOUNT_ADDENTRY, data, len);
+ rpc_req(PROG_MOUNT, MOUNT_ADDENTRY, data, len);
}
/**************************************************************************
NFS_UMOUNTALL - Unmount all our NFS Filesystems on the Server
**************************************************************************/
-static void
-nfs_umountall_req (void)
+static void nfs_umountall_req(void)
{
uint32_t data[1024];
uint32_t *p;
int len;
- if ((NfsSrvMountPort == -1) || (!fs_mounted)) {
+ if (nfs_server_mount_port < 0)
/* Nothing mounted, nothing to umount */
return;
- }
p = &(data[0]);
- p = (uint32_t *)rpc_add_credentials ((long *)p);
+ p = rpc_add_credentials(p);
- len = (uint32_t *)p - (uint32_t *)&(data[0]);
+ len = p - &(data[0]);
- rpc_req (PROG_MOUNT, MOUNT_UMOUNTALL, data, len);
+ rpc_req(PROG_MOUNT, MOUNT_UMOUNTALL, data, len);
}
/***************************************************************************
@@ -240,29 +301,27 @@ nfs_umountall_req (void)
* In case of successful readlink(), the dirname is manipulated,
* so that inside the nfs() function a recursion can be done.
**************************************************************************/
-static void
-nfs_readlink_req (void)
+static void nfs_readlink_req(void)
{
uint32_t data[1024];
uint32_t *p;
int len;
p = &(data[0]);
- p = (uint32_t *)rpc_add_credentials ((long *)p);
+ p = rpc_add_credentials(p);
memcpy (p, filefh, NFS_FHSIZE);
p += (NFS_FHSIZE / 4);
- len = (uint32_t *)p - (uint32_t *)&(data[0]);
+ len = p - &(data[0]);
- rpc_req (PROG_NFS, NFS_READLINK, data, len);
+ rpc_req(PROG_NFS, NFS_READLINK, data, len);
}
/**************************************************************************
NFS_LOOKUP - Lookup Pathname
**************************************************************************/
-static void
-nfs_lookup_req (char *fname)
+static void nfs_lookup_req(char *fname)
{
uint32_t data[1024];
uint32_t *p;
@@ -272,32 +331,32 @@ nfs_lookup_req (char *fname)
fnamelen = strlen (fname);
p = &(data[0]);
- p = (uint32_t *)rpc_add_credentials ((long *)p);
+ p = rpc_add_credentials(p);
memcpy (p, dirfh, NFS_FHSIZE);
p += (NFS_FHSIZE / 4);
*p++ = htonl(fnamelen);
- if (fnamelen & 3) *(p + fnamelen / 4) = 0;
+ if (fnamelen & 3)
+ *(p + fnamelen / 4) = 0;
memcpy (p, fname, fnamelen);
p += (fnamelen + 3) / 4;
- len = (uint32_t *)p - (uint32_t *)&(data[0]);
+ len = p - &(data[0]);
- rpc_req (PROG_NFS, NFS_LOOKUP, data, len);
+ rpc_req(PROG_NFS, NFS_LOOKUP, data, len);
}
/**************************************************************************
NFS_READ - Read File on NFS Server
**************************************************************************/
-static void
-nfs_read_req (int offset, int readlen)
+static void nfs_read_req(int offset, int readlen)
{
uint32_t data[1024];
uint32_t *p;
int len;
p = &(data[0]);
- p = (uint32_t *)rpc_add_credentials ((long *)p);
+ p = rpc_add_credentials(p);
memcpy (p, filefh, NFS_FHSIZE);
p += (NFS_FHSIZE / 4);
@@ -305,238 +364,194 @@ nfs_read_req (int offset, int readlen)
*p++ = htonl(readlen);
*p++ = 0;
- len = (uint32_t *)p - (uint32_t *)&(data[0]);
+ len = p - &(data[0]);
- rpc_req (PROG_NFS, NFS_READ, data, len);
+ rpc_req(PROG_NFS, NFS_READ, data, len);
}
/**************************************************************************
RPC request dispatcher
**************************************************************************/
-
-static void
-NfsSend (void)
+static void nfs_send(void)
{
-#ifdef NFS_DEBUG
- printf ("%s\n", __FUNCTION__);
-#endif
+ debug("%s\n", __func__);
- switch (NfsState) {
+ switch (nfs_state) {
case STATE_PRCLOOKUP_PROG_MOUNT_REQ:
- rpc_lookup_req (PROG_MOUNT, 1);
+ rpc_lookup_req(PROG_MOUNT, 1);
break;
case STATE_PRCLOOKUP_PROG_NFS_REQ:
- rpc_lookup_req (PROG_NFS, 2);
+ rpc_lookup_req(PROG_NFS, 2);
break;
case STATE_MOUNT_REQ:
- nfs_mount_req (nfs_path);
+ nfs_mount_req(nfs_path);
break;
case STATE_UMOUNT_REQ:
- nfs_umountall_req ();
+ nfs_umountall_req();
break;
case STATE_LOOKUP_REQ:
- nfs_lookup_req (nfs_filename);
+ nfs_lookup_req(nfs_filename);
break;
case STATE_READ_REQ:
- nfs_read_req (nfs_offset, nfs_len);
+ nfs_read_req(nfs_offset, NFS_READ_SIZE);
break;
case STATE_READLINK_REQ:
- nfs_readlink_req ();
+ nfs_readlink_req();
break;
}
}
-/**************************************************************************
-Handlers for the reply from server
-**************************************************************************/
-
-static int
-rpc_lookup_reply (int prog, uchar *pkt, unsigned len)
+static int rpc_check_reply(unsigned char *pkt, int isnfs)
{
- struct rpc_t rpc_pkt;
-
- memcpy ((unsigned char *)&rpc_pkt, pkt, len);
+ uint32_t *data;
+ int nfserr;
+ struct rpc_reply rpc;
-#ifdef NFS_DEBUG
- printf ("%s\n", __FUNCTION__);
-#endif
+ memcpy(&rpc, pkt, sizeof(rpc));
- if (ntohl(rpc_pkt.u.reply.id) != rpc_id)
- return -1;
+ if (ntohl(rpc.id) != rpc_id)
+ return -EINVAL;
- if (rpc_pkt.u.reply.rstatus ||
- rpc_pkt.u.reply.verifier ||
- rpc_pkt.u.reply.astatus ||
- rpc_pkt.u.reply.astatus) {
- return -1;
+ if (rpc.rstatus ||
+ rpc.verifier ||
+ rpc.astatus ) {
+ return -EINVAL;
}
+ if (!isnfs)
+ return 0;
+
+ data = (uint32_t *)(pkt + sizeof(struct rpc_reply));
+ nfserr = ntohl(net_read_uint32(data));
+
+ debug("%s: state: %d, err %d\n", __func__, nfs_state, -nfserr);
+
+ if (nfserr <= 30)
+ /* These nfs codes correspond with those in errno.h */
+ return -nfserr;
+ if (nfserr == NFSERR_STALE)
+ return -ESTALE;
+
+ return -EINVAL;
+}
+
+static int rpc_lookup_reply(int prog, unsigned char *pkt, unsigned len)
+{
+ uint32_t port;
+ int ret;
+
+ ret = rpc_check_reply(pkt, 0);
+ if (ret)
+ return ret;
+
+ port = net_read_uint32((uint32_t *)(pkt + sizeof(struct rpc_reply)));
switch (prog) {
case PROG_MOUNT:
- NfsSrvMountPort = ntohl(rpc_pkt.u.reply.data[0]);
+ nfs_server_mount_port = ntohl(port);
break;
case PROG_NFS:
- NfsSrvNfsPort = ntohl(rpc_pkt.u.reply.data[0]);
+ nfs_server_nfs_port = ntohl(port);
break;
}
return 0;
}
-static int
-nfs_mount_reply (uchar *pkt, unsigned len)
+static int nfs_mount_reply(unsigned char *pkt, unsigned len)
{
- struct rpc_t rpc_pkt;
-
-#ifdef NFS_DEBUG
- printf ("%s\n", __FUNCTION__);
-#endif
-
- memcpy ((unsigned char *)&rpc_pkt, pkt, len);
-
- if (ntohl(rpc_pkt.u.reply.id) != rpc_id)
- return -1;
+ int ret;
- if (rpc_pkt.u.reply.rstatus ||
- rpc_pkt.u.reply.verifier ||
- rpc_pkt.u.reply.astatus ||
- rpc_pkt.u.reply.data[0]) {
- return -1;
- }
+ ret = rpc_check_reply(pkt, 1);
+ if (ret)
+ return ret;
- fs_mounted = 1;
- memcpy (dirfh, rpc_pkt.u.reply.data + 1, NFS_FHSIZE);
+ memcpy(dirfh, pkt + sizeof(struct rpc_reply) + 4, NFS_FHSIZE);
return 0;
}
-static int
-nfs_umountall_reply (uchar *pkt, unsigned len)
+static int nfs_umountall_reply(unsigned char *pkt, unsigned len)
{
- struct rpc_t rpc_pkt;
-
-#ifdef NFS_DEBUG
- printf ("%s\n", __FUNCTION__);
-#endif
-
- memcpy ((unsigned char *)&rpc_pkt, pkt, len);
-
- if (ntohl(rpc_pkt.u.reply.id) != rpc_id)
- return -1;
+ int ret;
- if (rpc_pkt.u.reply.rstatus ||
- rpc_pkt.u.reply.verifier ||
- rpc_pkt.u.reply.astatus) {
- return -1;
- }
+ ret = rpc_check_reply(pkt, 0);
+ if (ret)
+ return ret;
- fs_mounted = 0;
- memset (dirfh, 0, sizeof(dirfh));
+ memset(dirfh, 0, sizeof(dirfh));
return 0;
}
-static int
-nfs_lookup_reply (uchar *pkt, unsigned len)
+static int nfs_lookup_reply(unsigned char *pkt, unsigned len)
{
- struct rpc_t rpc_pkt;
-
-#ifdef NFS_DEBUG
- printf ("%s\n", __FUNCTION__);
-#endif
-
- memcpy ((unsigned char *)&rpc_pkt, pkt, len);
-
- if (ntohl(rpc_pkt.u.reply.id) != rpc_id)
- return -1;
+ int ret;
- if (rpc_pkt.u.reply.rstatus ||
- rpc_pkt.u.reply.verifier ||
- rpc_pkt.u.reply.astatus ||
- rpc_pkt.u.reply.data[0]) {
- return -1;
- }
+ ret = rpc_check_reply(pkt, 1);
+ if (ret)
+ return ret;
- memcpy (filefh, rpc_pkt.u.reply.data + 1, NFS_FHSIZE);
+ memcpy(filefh, pkt + sizeof(struct rpc_reply) + 4, NFS_FHSIZE);
return 0;
}
-static int
-nfs_readlink_reply (uchar *pkt, unsigned len)
+static int nfs_readlink_reply(unsigned char *pkt, unsigned len)
{
- struct rpc_t rpc_pkt;
+ uint32_t *data;
+ char *path;
int rlen;
+ int ret;
-#ifdef NFS_DEBUG
- printf ("%s\n", __FUNCTION__);
-#endif
+ ret = rpc_check_reply(pkt, 1);
+ if (ret)
+ return ret;
- memcpy ((unsigned char *)&rpc_pkt, pkt, len);
+ data = (uint32_t *)(pkt + sizeof(struct rpc_reply));
- if (ntohl(rpc_pkt.u.reply.id) != rpc_id)
- return -1;
+ data++;
- if (rpc_pkt.u.reply.rstatus ||
- rpc_pkt.u.reply.verifier ||
- rpc_pkt.u.reply.astatus ||
- rpc_pkt.u.reply.data[0]) {
- return -1;
- }
+ rlen = ntohl(net_read_uint32(data)); /* new path length */
- rlen = ntohl (rpc_pkt.u.reply.data[1]); /* new path length */
+ data++;
+ path = (char *)data;
- if (*((char *)&(rpc_pkt.u.reply.data[2])) != '/') {
- int pathlen;
- strcat (nfs_path, "/");
- pathlen = strlen(nfs_path);
- memcpy (nfs_path+pathlen, (uchar *)&(rpc_pkt.u.reply.data[2]), rlen);
- nfs_path[pathlen+rlen+1] = 0;
+ if (*path != '/') {
+ strcat(nfs_path, "/");
+ strncat(nfs_path, path, rlen);
} else {
- memcpy (nfs_path, (uchar *)&(rpc_pkt.u.reply.data[2]), rlen);
+ memcpy(nfs_path, path, rlen);
nfs_path[rlen] = 0;
}
return 0;
}
-static int
-nfs_read_reply (uchar *pkt, unsigned len)
+static int nfs_read_reply(unsigned char *pkt, unsigned len)
{
- struct rpc_t rpc_pkt;
int rlen;
+ uint32_t *data;
+ int ret;
-#ifdef NFS_DEBUG_nop
- printf ("%s\n", __FUNCTION__);
-#endif
-
- memcpy ((uchar *)&rpc_pkt, pkt, sizeof(rpc_pkt.u.reply));
+ debug("%s\n", __func__);
- if (ntohl(rpc_pkt.u.reply.id) != rpc_id)
- return -1;
+ ret = rpc_check_reply(pkt, 1);
+ if (ret)
+ return ret;
- if (rpc_pkt.u.reply.rstatus ||
- rpc_pkt.u.reply.verifier ||
- rpc_pkt.u.reply.astatus ||
- rpc_pkt.u.reply.data[0]) {
- if (rpc_pkt.u.reply.rstatus) {
- return -9999;
- }
- if (rpc_pkt.u.reply.astatus) {
- return -9999;
- }
- return -ntohl(rpc_pkt.u.reply.data[0]);;
- }
+ data = (uint32_t *)(pkt + sizeof(struct rpc_reply));
- if ((nfs_offset!=0) && !((nfs_offset) % (NFS_READ_SIZE/2*10*HASHES_PER_LINE))) {
+ if (nfs_offset && !((nfs_offset) % (NFS_READ_SIZE / 2 * 10 * HASHES_PER_LINE)))
puts ("\n\t ");
- }
- if (!(nfs_offset % ((NFS_READ_SIZE/2)*10))) {
+ if (!(nfs_offset % ((NFS_READ_SIZE / 2) * 10)))
putchar ('#');
- }
- rlen = ntohl(rpc_pkt.u.reply.data[18]);
- if ( store_block ((uchar *)pkt+sizeof(rpc_pkt.u.reply), nfs_offset, rlen) )
- return -9999;
+ rlen = ntohl(net_read_uint32(data + 18));
+
+ ret = write(net_store_fd, (char *)(data + 19), rlen);
+ if (ret < 0) {
+ perror("write");
+ return ret;
+ }
return rlen;
}
@@ -545,170 +560,116 @@ nfs_read_reply (uchar *pkt, unsigned len)
Interfaces of barebox
**************************************************************************/
-static void
-NfsTimeout (void)
+static void nfs_handler(char *packet, unsigned len)
{
- puts ("Timeout\n");
- NetState = NETLOOP_FAIL;
- return;
-}
-
-static void
-NfsHandler (uchar *pkt, unsigned dest, unsigned src, unsigned len)
-{
- int rlen;
-
-#ifdef NFS_DEBUG
- printf ("%s\n", __FUNCTION__);
-#endif
+ char *pkt = net_eth_to_udp_payload(packet);
+ int ret;
- if (dest != NfsOurPort) return;
+ debug("%s\n", __func__);
- switch (NfsState) {
+ switch (nfs_state) {
case STATE_PRCLOOKUP_PROG_MOUNT_REQ:
- rpc_lookup_reply (PROG_MOUNT, pkt, len);
- NfsState = STATE_PRCLOOKUP_PROG_NFS_REQ;
- NfsSend ();
+ ret = rpc_lookup_reply(PROG_MOUNT, pkt, len);
+ if (ret)
+ goto err_out;
+ nfs_state = STATE_PRCLOOKUP_PROG_NFS_REQ;
break;
case STATE_PRCLOOKUP_PROG_NFS_REQ:
- rpc_lookup_reply (PROG_NFS, pkt, len);
- NfsState = STATE_MOUNT_REQ;
- NfsSend ();
+ ret = rpc_lookup_reply(PROG_NFS, pkt, len);
+ if (ret)
+ goto err_out;
+ nfs_state = STATE_MOUNT_REQ;
break;
case STATE_MOUNT_REQ:
- if (nfs_mount_reply(pkt, len)) {
- puts ("*** ERROR: Cannot mount\n");
- /* just to be sure... */
- NfsState = STATE_UMOUNT_REQ;
- NfsSend ();
- } else {
- NfsState = STATE_LOOKUP_REQ;
- NfsSend ();
- }
+ ret = nfs_mount_reply(pkt, len);
+ if (ret)
+ goto err_out;
+
+ nfs_state = STATE_LOOKUP_REQ;
break;
case STATE_UMOUNT_REQ:
- if (nfs_umountall_reply(pkt, len)) {
- puts ("*** ERROR: Cannot umount\n");
- NetState = NETLOOP_FAIL;
- } else {
- puts ("\ndone\n");
- NetState = NfsDownloadState;
- }
- break;
+ ret = nfs_umountall_reply(pkt, len);
+ if (ret)
+ nfs_err = ret;
+ nfs_state = STATE_DONE;
+ return;
case STATE_LOOKUP_REQ:
- if (nfs_lookup_reply(pkt, len)) {
- puts ("*** ERROR: File lookup fail\n");
- NfsState = STATE_UMOUNT_REQ;
- NfsSend ();
- } else {
- NfsState = STATE_READ_REQ;
- nfs_offset = 0;
- nfs_len = NFS_READ_SIZE;
- NfsSend ();
- }
+ ret = nfs_lookup_reply(pkt, len);
+ if (ret)
+ goto err_umount;
+
+ nfs_state = STATE_READ_REQ;
+ nfs_offset = 0;
break;
case STATE_READLINK_REQ:
- if (nfs_readlink_reply(pkt, len)) {
- puts ("*** ERROR: Symlink fail\n");
- NfsState = STATE_UMOUNT_REQ;
- NfsSend ();
- } else {
-#ifdef NFS_DEBUG
- printf ("Symlink --> %s\n", nfs_path);
-#endif
- nfs_filename = basename (nfs_path);
- nfs_path = dirname (nfs_path);
-
- NfsState = STATE_MOUNT_REQ;
- NfsSend ();
- }
+ ret = nfs_readlink_reply(pkt, len);
+ if (ret)
+ goto err_umount;
+
+ debug("Symlink --> %s\n", nfs_path);
+
+ nfs_filename = basename(nfs_path);
+ nfs_path = dirname(nfs_path);
+
+ nfs_state = STATE_MOUNT_REQ;
break;
case STATE_READ_REQ:
- rlen = nfs_read_reply (pkt, len);
- NetSetTimeout (NFS_TIMEOUT * SECOND, NfsTimeout);
- if (rlen > 0) {
- nfs_offset += rlen;
- NfsSend ();
- }
- else if ((rlen == -NFSERR_ISDIR)||(rlen == -NFSERR_INVAL)) {
+ ret = nfs_read_reply(pkt, len);
+ nfs_timer_start = get_time_ns();
+ if (ret > 0)
+ nfs_offset += ret;
+ else if (ret == -EISDIR || ret == -EINVAL)
/* symbolic link */
- NfsState = STATE_READLINK_REQ;
- NfsSend ();
- } else {
- if ( ! rlen ) NfsDownloadState = NETLOOP_SUCCESS;
- NfsState = STATE_UMOUNT_REQ;
- NfsSend ();
- }
+ nfs_state = STATE_READLINK_REQ;
+ else
+ goto err_umount;
+
break;
}
-}
+ nfs_send();
+
+ return;
+
+err_umount:
+ nfs_state = STATE_UMOUNT_REQ;
+ nfs_err = ret;
+ nfs_send();
+ return;
+
+err_out:
+ nfs_state = STATE_DONE;
+ nfs_err = ret;
+}
-void
-NfsStart (char *p)
+static void nfs_start(char *p)
{
-#ifdef NFS_DEBUG
- printf ("%s\n", __FUNCTION__);
-#endif
- NfsDownloadState = NETLOOP_FAIL;
+ debug("%s\n", __func__);
- NfsServerIP = NetServerIP;
nfs_path = (char *)nfs_path_buff;
- if (nfs_path == NULL) {
- NetState = NETLOOP_FAIL;
- puts ("*** ERROR: Fail allocate memory\n");
- return;
- }
-
- strcpy (nfs_path, p);
+ strcpy(nfs_path, p);
nfs_filename = basename (nfs_path);
nfs_path = dirname (nfs_path);
-#if defined(CONFIG_NET_MULTI)
- printf ("Using %s device\n", eth_get_name());
-#endif
+ printf("\nFilename '%s/%s'.\nLoading: ", nfs_path, nfs_filename);
- puts ("File transfer via NFS from server "); print_IPaddr (NfsServerIP);
- puts ("; our IP address is "); print_IPaddr (NetOurIP);
+ nfs_timer_start = get_time_ns();
- /* Check if we need to send across this subnet */
- if (NetOurGatewayIP && NetOurSubnetMask) {
- IPaddr_t OurNet = NetOurIP & NetOurSubnetMask;
- IPaddr_t ServerNet = NetServerIP & NetOurSubnetMask;
+ nfs_state = STATE_PRCLOOKUP_PROG_MOUNT_REQ;
- if (OurNet != ServerNet) {
- puts ("; sending through gateway ");
- print_IPaddr (NetOurGatewayIP) ;
- }
- }
- printf ("\nFilename '%s/%s'.", nfs_path, nfs_filename);
-
- NetSetTimeout (NFS_TIMEOUT * SECOND, NfsTimeout);
- NetSetHandler (NfsHandler);
-
- NfsTimeoutCount = 0;
- NfsState = STATE_PRCLOOKUP_PROG_MOUNT_REQ;
-
- /*FIX ME !!!*/
- NfsOurPort = 1000;
-
- /* zero out server ether in case the server ip has changed */
- memset (NetServerEther, 0, 6);
-
- NfsSend ();
+ nfs_send();
}
static int do_nfs(struct command *cmdtp, int argc, char *argv[])
{
- int rcode = 0;
char *localfile;
char *remotefile;
@@ -728,23 +689,38 @@ static int do_nfs(struct command *cmdtp, int argc, char *argv[])
return 1;
}
- if (NetLoopInit(NFS) < 0)
- goto out;
+ nfs_con = net_udp_new(net_get_serverip(), 0, nfs_handler);
+ if (IS_ERR(nfs_con)) {
+ nfs_err = PTR_ERR(nfs_con);
+ goto err_udp;
+ }
+ net_udp_bind(nfs_con, 1000);
- NfsStart(remotefile);
+ nfs_err = 0;
- rcode = NetLoop();
- if (rcode < 0) {
- rcode = 1;
- goto out;
- }
+ nfs_start(remotefile);
- /* NetLoop ok, update environment */
- netboot_update_env();
+ while (nfs_state != STATE_DONE) {
+ if (ctrlc()) {
+ nfs_err = -EINTR;
+ break;
+ }
+ net_poll();
+ if (is_timeout(nfs_timer_start, NFS_TIMEOUT * SECOND))
+ break;
+ }
-out:
+ net_unregister(nfs_con);
+err_udp:
close(net_store_fd);
- return rcode;
+ if (nfs_err) {
+ printf("NFS failed: %s\n", strerror(-nfs_err));
+ unlink(localfile);
+ }
+
+ printf("\n");
+
+ return nfs_err == 0 ? 0 : 1;
}
static const __maybe_unused char cmd_nfs_help[] =
--
1.7.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 08/13] net: consider rarp support as outdated. Remove it
2010-06-04 9:54 reworking the network stack Sascha Hauer
` (6 preceding siblings ...)
2010-06-04 9:55 ` [PATCH 07/13] implement nfs " Sascha Hauer
@ 2010-06-04 9:55 ` Sascha Hauer
2010-06-04 9:55 ` [PATCH 09/13] network drivers: call net_receive directly instead of NetReceive Sascha Hauer
` (4 subsequent siblings)
12 siblings, 0 replies; 18+ messages in thread
From: Sascha Hauer @ 2010-06-04 9:55 UTC (permalink / raw)
To: barebox
It is disabled in all defconfigs and probably broken for longer.
Remove it.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
net/Kconfig | 4 --
net/Makefile | 1 -
net/rarp.c | 101 ----------------------------------------------------------
3 files changed, 0 insertions(+), 106 deletions(-)
delete mode 100644 net/rarp.c
diff --git a/net/Kconfig b/net/Kconfig
index cca2b00..a110bec 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -7,10 +7,6 @@ config NET_DHCP
bool
prompt "dhcp support"
-config NET_RARP
- bool
- prompt "rarp protocol support"
-
config NET_NFS
bool
prompt "nfs support"
diff --git a/net/Makefile b/net/Makefile
index 0ffc895..bba6f0e 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -2,6 +2,5 @@ obj-$(CONFIG_NET_DHCP) += dhcp.o
obj-$(CONFIG_NET) += eth.o
obj-$(CONFIG_NET) += net.o
obj-$(CONFIG_NET_NFS) += nfs.o
-obj-$(CONFIG_NET_RARP) += rarp.o
obj-$(CONFIG_NET_TFTP) += tftp.o
obj-$(CONFIG_NET_PING) += ping.o
diff --git a/net/rarp.c b/net/rarp.c
deleted file mode 100644
index 24818f8..0000000
--- a/net/rarp.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * (C) Copyright 2000-2002
- * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
- *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
- */
-
-#include <common.h>
-#include <command.h>
-#include <clock.h>
-#include <net.h>
-#include "nfs.h"
-#include "rarp.h"
-#include "tftp.h"
-
-#define TIMEOUT 5 /* Seconds before trying BOOTP again */
-#ifndef CONFIG_NET_RETRY_COUNT
-# define TIMEOUT_COUNT 5 /* # of timeouts before giving up */
-#else
-# define TIMEOUT_COUNT (CONFIG_NET_RETRY_COUNT)
-#endif
-
-
-int RarpTry;
-
-/*
- * Handle a RARP received packet.
- */
-static void
-RarpHandler(uchar * dummi0, unsigned dummi1, unsigned dummi2, unsigned dummi3)
-{
-#ifdef DEBUG
- puts ("Got good RARP\n");
-#endif
- NetState = NETLOOP_SUCCESS;
-}
-
-
-/*
- * Timeout on BOOTP request.
- */
-static void
-RarpTimeout(void)
-{
- NetSetTimeout (TIMEOUT * SECOND, RarpTimeout);
- RarpRequest ();
-}
-
-
-void
-RarpRequest (void)
-{
- int i;
- uchar *pkt;
- ARP_t * rarp;
-
- NetOurIP = 0;
- RarpTry = 0;
-
- printf("RARP broadcast %d\n", ++RarpTry);
- pkt = NetTxPacket;
-
- pkt += NetSetEther(pkt, NetBcastAddr, PROT_RARP);
-
- rarp = (ARP_t *)pkt;
-
- rarp->ar_hrd = htons (ARP_ETHER);
- rarp->ar_pro = htons (PROT_IP);
- rarp->ar_hln = 6;
- rarp->ar_pln = 4;
- rarp->ar_op = htons (RARPOP_REQUEST);
- memcpy (&rarp->ar_data[0], NetOurEther, 6); /* source ET addr */
- memcpy (&rarp->ar_data[6], &NetOurIP, 4); /* source IP addr */
- memcpy (&rarp->ar_data[10], NetOurEther, 6); /* dest ET addr = source ET addr ??*/
- /* dest. IP addr set to broadcast */
- for (i = 0; i <= 3; i++) {
- rarp->ar_data[16 + i] = 0xff;
- }
-
- NetSendPacket(NetTxPacket, (pkt - NetTxPacket) + ARP_HDR_SIZE);
-
- NetSetTimeout(TIMEOUT * SECOND, RarpTimeout);
- NetSetHandler(RarpHandler);
-}
-
--
1.7.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 09/13] network drivers: call net_receive directly instead of NetReceive
2010-06-04 9:54 reworking the network stack Sascha Hauer
` (7 preceding siblings ...)
2010-06-04 9:55 ` [PATCH 08/13] net: consider rarp support as outdated. Remove it Sascha Hauer
@ 2010-06-04 9:55 ` Sascha Hauer
2010-06-04 9:55 ` [PATCH 10/13] net: remove old network stack Sascha Hauer
` (3 subsequent siblings)
12 siblings, 0 replies; 18+ messages in thread
From: Sascha Hauer @ 2010-06-04 9:55 UTC (permalink / raw)
To: barebox
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/net/at91_ether.c | 2 +-
drivers/net/cs8900.c | 2 +-
drivers/net/dm9000.c | 2 +-
drivers/net/ep93xx.c | 4 ++--
drivers/net/fec_imx.c | 2 +-
drivers/net/fec_mpc5200.c | 2 +-
drivers/net/macb.c | 2 +-
drivers/net/netx_eth.c | 2 +-
drivers/net/smc91111.c | 2 +-
drivers/net/smc911x.c | 2 +-
drivers/net/tap.c | 2 +-
drivers/net/usb/asix.c | 2 +-
drivers/net/usb/usbnet.c | 2 +-
13 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/drivers/net/at91_ether.c b/drivers/net/at91_ether.c
index a2d1594..3c4f4b0 100644
--- a/drivers/net/at91_ether.c
+++ b/drivers/net/at91_ether.c
@@ -190,7 +190,7 @@ static int at91rm9200_eth_rx (struct eth_device *edev)
return 0;
size = rbfp->size & RBF_SIZE;
- NetReceive ((volatile uchar *) (rbfp->addr & RBF_ADDR), size);
+ net_receive((volatile uchar *) (rbfp->addr & RBF_ADDR), size);
rbfp->addr &= ~RBF_OWNER;
if (rbfp->addr & RBF_WRAP)
diff --git a/drivers/net/cs8900.c b/drivers/net/cs8900.c
index 64366ac..8120877 100644
--- a/drivers/net/cs8900.c
+++ b/drivers/net/cs8900.c
@@ -309,7 +309,7 @@ static int cs8900_recv(struct eth_device *dev)
if (len & 1) {
*addr++ = readw(priv->regs + CS8900_RTDATA0);
}
- NetReceive(NetRxPackets[0], len);
+ net_receive(NetRxPackets[0], len);
return len;
}
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
index 77c771b..2062c66 100644
--- a/drivers/net/dm9000.c
+++ b/drivers/net/dm9000.c
@@ -416,7 +416,7 @@ static int dm9000_eth_rx (struct eth_device *edev)
/* Pass to upper layer */
debug("passing packet to upper layer\n");
- NetReceive(NetRxPackets[0], RxLen);
+ net_receive(NetRxPackets[0], RxLen);
return RxLen;
}
return 0;
diff --git a/drivers/net/ep93xx.c b/drivers/net/ep93xx.c
index e91a92e..c6c4671 100644
--- a/drivers/net/ep93xx.c
+++ b/drivers/net/ep93xx.c
@@ -335,9 +335,9 @@ static int ep93xx_eth_rcv_packet(struct eth_device *edev)
* protocol stack. We track the total number of
* bytes in the frame (nbytes_frame) which will be
* used when we pass the data off to the protocol
- * layer via NetReceive().
+ * layer via net_receive().
*/
- NetReceive((uchar *)priv->rx_dq.current->word1,
+ net_receive((uchar *)priv->rx_dq.current->word1,
RX_STATUS_FRAME_LEN(priv->rx_sq.current));
pr_debug("reporting %d bytes...\n",
RX_STATUS_FRAME_LEN(priv->rx_sq.current));
diff --git a/drivers/net/fec_imx.c b/drivers/net/fec_imx.c
index 5e8e5ca..40a7543 100644
--- a/drivers/net/fec_imx.c
+++ b/drivers/net/fec_imx.c
@@ -515,7 +515,7 @@ static int fec_recv(struct eth_device *dev)
*/
frame = phys_to_virt(readl(&rbd->data_pointer));
frame_length = readw(&rbd->data_length) - 4;
- NetReceive(frame->data, frame_length);
+ net_receive(frame->data, frame_length);
len = frame_length;
} else {
if (bd_status & FEC_RBD_ERR) {
diff --git a/drivers/net/fec_mpc5200.c b/drivers/net/fec_mpc5200.c
index d803ddf..ce9a21d 100644
--- a/drivers/net/fec_mpc5200.c
+++ b/drivers/net/fec_mpc5200.c
@@ -645,7 +645,7 @@ static int mpc5xxx_fec_recv(struct eth_device *dev)
*/
memcpy(buff, frame->head, 14);
memcpy(buff + 14, frame->data, frame_length);
- NetReceive(buff, frame_length);
+ net_receive(buff, frame_length);
len = frame_length;
}
/*
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index 1bb833a..4feeed0 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -190,7 +190,7 @@ static int macb_recv(struct eth_device *edev)
buffer = (void *)NetRxPackets[0];
}
- NetReceive(buffer, length);
+ net_receive(buffer, length);
if (++rx_tail >= CFG_MACB_RX_RING_SIZE)
rx_tail = 0;
reclaim_rx_buffers(macb, rx_tail);
diff --git a/drivers/net/netx_eth.c b/drivers/net/netx_eth.c
index 673007a..f2d7b4a 100644
--- a/drivers/net/netx_eth.c
+++ b/drivers/net/netx_eth.c
@@ -111,7 +111,7 @@ static int netx_eth_rx (struct eth_device *edev)
/* get data */
memcpy((void*)NetRxPackets[0], (void *)(SRAM_BASE(seg) + frameno * 1560), len);
/* pass to barebox */
- NetReceive(NetRxPackets[0], len);
+ net_receive(NetRxPackets[0], len);
PFIFO_REG(PFIFO_BASE(EMPTY_PTR_FIFO(xcno))) =
FIFO_PTR_SEGMENT(seg) |
diff --git a/drivers/net/smc91111.c b/drivers/net/smc91111.c
index 9b41c67..58ebaa9 100644
--- a/drivers/net/smc91111.c
+++ b/drivers/net/smc91111.c
@@ -1156,7 +1156,7 @@ static int smc91c111_eth_rx(struct eth_device *edev)
if (!is_error) {
/* Pass the packet up to the protocol layers. */
- NetReceive(NetRxPackets[0], packet_length);
+ net_receive(NetRxPackets[0], packet_length);
return packet_length;
}
diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c
index 4a5e7b6..ca320d5 100644
--- a/drivers/net/smc911x.c
+++ b/drivers/net/smc911x.c
@@ -668,7 +668,7 @@ static int smc911x_eth_rx(struct eth_device *edev)
": dropped bad packet. Status: 0x%08x\n",
status);
else
- NetReceive(NetRxPackets[0], pktlen);
+ net_receive(NetRxPackets[0], pktlen);
}
return 0;
diff --git a/drivers/net/tap.c b/drivers/net/tap.c
index 8673436..522a9f1 100644
--- a/drivers/net/tap.c
+++ b/drivers/net/tap.c
@@ -48,7 +48,7 @@ int tap_eth_rx (struct eth_device *edev)
length = linux_read_nonblock(priv->fd, NetRxPackets[0], PKTSIZE);
if (length > 0)
- NetReceive(NetRxPackets[0], length);
+ net_receive(NetRxPackets[0], length);
return 0;
}
diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c
index e44ce67..fc4146f 100644
--- a/drivers/net/usb/asix.c
+++ b/drivers/net/usb/asix.c
@@ -425,7 +425,7 @@ static int asix_rx_fixup(struct usbnet *dev, void *buf, int len)
return 0;
}
- NetReceive(buf, size);
+ net_receive(buf, size);
buf += ((size + 1) & 0xfffe);
len -= ((size + 1) & 0xfffe);
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 123cc3b..b0e3090 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -137,7 +137,7 @@ static int usbnet_recv(struct eth_device *edev)
if (info->rx_fixup)
return info->rx_fixup(dev, rx_buf, alen);
else
- NetReceive(rx_buf, alen);
+ net_receive(rx_buf, alen);
}
return 0;
--
1.7.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 10/13] net: remove old network stack
2010-06-04 9:54 reworking the network stack Sascha Hauer
` (8 preceding siblings ...)
2010-06-04 9:55 ` [PATCH 09/13] network drivers: call net_receive directly instead of NetReceive Sascha Hauer
@ 2010-06-04 9:55 ` Sascha Hauer
2010-06-04 9:55 ` [PATCH 11/13] rework device parameters Sascha Hauer
` (2 subsequent siblings)
12 siblings, 0 replies; 18+ messages in thread
From: Sascha Hauer @ 2010-06-04 9:55 UTC (permalink / raw)
To: barebox
All network commands now use the new stack, so remove the old one.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
commands/net.c | 42 ---
include/net.h | 359 +---------------------
net/net.c | 947 +++-----------------------------------------------------
3 files changed, 50 insertions(+), 1298 deletions(-)
diff --git a/commands/net.c b/commands/net.c
index 949963f..938463c 100644
--- a/commands/net.c
+++ b/commands/net.c
@@ -35,48 +35,6 @@
#include <errno.h>
#include <libbb.h>
-void netboot_update_env(void)
-{
- struct eth_device *eth_current = eth_get_current();
- char tmp[22];
- IPaddr_t net_gateway_ip = NetOurGatewayIP;
- IPaddr_t net_ip = NetOurIP;
- IPaddr_t net_server_ip = NetServerIP;
- IPaddr_t netmask = NetOurSubnetMask;
-
- if (net_gateway_ip)
- dev_set_param_ip(ð_current->dev, "gateway", net_gateway_ip);
-
- if (netmask)
- dev_set_param_ip(ð_current->dev, "netmask", netmask);
-
-
- if (NetOurHostName[0])
- setenv ("hostname", NetOurHostName);
-
- if (NetOurRootPath[0])
- setenv ("rootpath", NetOurRootPath);
-
- if (net_ip)
- dev_set_param_ip(ð_current->dev, "ipaddr", net_ip);
-
- if (net_server_ip)
- dev_set_param_ip(ð_current->dev, "serverip", net_server_ip);
-
- if (NetOurDNSIP) {
- ip_to_string (NetOurDNSIP, tmp);
- setenv ("dnsip", tmp);
- }
-#ifdef CONFIG_BOOTP_DNS2
- if (NetOurDNS2IP) {
- ip_to_string (NetOurDNS2IP, tmp);
- setenv ("dnsip2", tmp);
- }
-#endif
- if (NetOurNISDomain[0])
- setenv ("domain", NetOurNISDomain);
-}
-
#ifdef CONFIG_NET_RARP
extern void RarpRequest(void);
diff --git a/include/net.h b/include/net.h
index f588a3d..627b18b 100644
--- a/include/net.h
+++ b/include/net.h
@@ -19,39 +19,8 @@
#include <asm/byteorder.h> /* for nton* / ntoh* stuff */
-/*
- * The number of receive packet buffers, and the required packet buffer
- * alignment in memory.
- *
- */
-
-#ifdef CFG_RX_ETH_BUFFER
-# define PKTBUFSRX CFG_RX_ETH_BUFFER
-#else
-# define PKTBUFSRX 4
-#endif
-
-#define PKTALIGN 32
-
-/*
- * The current receive packet handler. Called with a pointer to the
- * application packet, and a protocol type (PORT_BOOTPC or PORT_TFTP).
- * All other packets are dealt with without calling the handler.
- */
-typedef void rxhand_f(uchar *, unsigned, unsigned, unsigned);
-
-/*
- * A timeout handler. Called after time interval has expired.
- */
-typedef void thand_f(void);
-
-#define NAMESIZE 16
-
-enum eth_state_t {
- ETH_STATE_INIT,
- ETH_STATE_PASSIVE,
- ETH_STATE_ACTIVE
-};
+/* The number of receive packet buffers */
+#define PKTBUFSRX 4
struct device_d;
@@ -92,328 +61,6 @@ int eth_rx(void); /* Check for received packets */
void eth_halt(void); /* stop SCC */
char *eth_get_name(void); /* get name of current device */
-
-/**********************************************************************/
-/*
- * Protocol headers.
- */
-
-/*
- * Ethernet header
- */
-typedef struct {
- uchar et_dest[6]; /* Destination node */
- uchar et_src[6]; /* Source node */
- ushort et_protlen; /* Protocol or length */
- uchar et_dsap; /* 802 DSAP */
- uchar et_ssap; /* 802 SSAP */
- uchar et_ctl; /* 802 control */
- uchar et_snap1; /* SNAP */
- uchar et_snap2;
- uchar et_snap3;
- ushort et_prot; /* 802 protocol */
-} Ethernet_t;
-
-#define ETHER_HDR_SIZE 14 /* Ethernet header size */
-#define E802_HDR_SIZE 22 /* 802 ethernet header size */
-
-/*
- * Ethernet header
- */
-typedef struct {
- uchar vet_dest[6]; /* Destination node */
- uchar vet_src[6]; /* Source node */
- ushort vet_vlan_type; /* PROT_VLAN */
- ushort vet_tag; /* TAG of VLAN */
- ushort vet_type; /* protocol type */
-} VLAN_Ethernet_t;
-
-#define VLAN_ETHER_HDR_SIZE 18 /* VLAN Ethernet header size */
-
-#define PROT_IP 0x0800 /* IP protocol */
-#define PROT_ARP 0x0806 /* IP ARP protocol */
-#define PROT_RARP 0x8035 /* IP ARP protocol */
-#define PROT_VLAN 0x8100 /* IEEE 802.1q protocol */
-
-#define IPPROTO_ICMP 1 /* Internet Control Message Protocol */
-#define IPPROTO_UDP 17 /* User Datagram Protocol */
-
-/*
- * Internet Protocol (IP) header.
- */
-typedef struct {
- uchar ip_hl_v; /* header length and version */
- uchar ip_tos; /* type of service */
- ushort ip_len; /* total length */
- ushort ip_id; /* identification */
- ushort ip_off; /* fragment offset field */
- uchar ip_ttl; /* time to live */
- uchar ip_p; /* protocol */
- ushort ip_sum; /* checksum */
- IPaddr_t ip_src; /* Source IP address */
- IPaddr_t ip_dst; /* Destination IP address */
- ushort udp_src; /* UDP source port */
- ushort udp_dst; /* UDP destination port */
- ushort udp_len; /* Length of UDP packet */
- ushort udp_xsum; /* Checksum */
-} IP_t;
-
-#define IP_HDR_SIZE_NO_UDP (sizeof (IP_t) - 8)
-#define IP_HDR_SIZE (sizeof (IP_t))
-
-
-/*
- * Address Resolution Protocol (ARP) header.
- */
-typedef struct
-{
- ushort ar_hrd; /* Format of hardware address */
-# define ARP_ETHER 1 /* Ethernet hardware address */
- ushort ar_pro; /* Format of protocol address */
- uchar ar_hln; /* Length of hardware address */
- uchar ar_pln; /* Length of protocol address */
- ushort ar_op; /* Operation */
-# define ARPOP_REQUEST 1 /* Request to resolve address */
-# define ARPOP_REPLY 2 /* Response to previous request */
-
-# define RARPOP_REQUEST 3 /* Request to resolve address */
-# define RARPOP_REPLY 4 /* Response to previous request */
-
- /*
- * The remaining fields are variable in size, according to
- * the sizes above, and are defined as appropriate for
- * specific hardware/protocol combinations.
- */
- uchar ar_data[0];
-} ARP_t;
-
-/*
- * ICMP stuff (just enough to handle (host) redirect messages)
- */
-#define ICMP_ECHO_REPLY 0 /* Echo reply */
-#define ICMP_REDIRECT 5 /* Redirect (change route) */
-#define ICMP_ECHO_REQUEST 8 /* Echo request */
-
-/* Codes for REDIRECT. */
-#define ICMP_REDIR_NET 0 /* Redirect Net */
-#define ICMP_REDIR_HOST 1 /* Redirect Host */
-
-typedef struct {
- uchar type;
- uchar code;
- ushort checksum;
- union {
- struct {
- ushort id;
- ushort sequence;
- } echo;
- ulong gateway;
- struct {
- ushort __unused;
- ushort mtu;
- } frag;
- } un;
-} ICMP_t;
-
-
-/*
- * Maximum packet size; used to allocate packet storage.
- * TFTP packets can be 524 bytes + IP header + ethernet header.
- * Lets be conservative, and go for 38 * 16. (Must also be
- * a multiple of 32 bytes).
- */
-/*
- * AS.HARNOIS : Better to set PKTSIZE to maximum size because
- * traffic type is not always controlled
- * maximum packet size = 1518
- * maximum packet size and multiple of 32 bytes = 1536
- */
-#define PKTSIZE 1518
-#define PKTSIZE_ALIGN 1536
-/*#define PKTSIZE 608*/
-
-/*
- * Maximum receive ring size; that is, the number of packets
- * we can buffer before overflow happens. Basically, this just
- * needs to be enough to prevent a packet being discarded while
- * we are processing the previous one.
- */
-#define RINGSZ 4
-#define RINGSZ_LOG2 2
-
-/**********************************************************************/
-/*
- * Globals.
- *
- * Note:
- *
- * All variables of type IPaddr_t are stored in NETWORK byte order
- * (big endian).
- */
-
-/* net.c */
-/** BOOTP EXTENTIONS **/
-extern IPaddr_t NetOurGatewayIP; /* Our gateway IP addresse */
-extern IPaddr_t NetOurSubnetMask; /* Our subnet mask (0 = unknown)*/
-extern IPaddr_t NetOurDNSIP; /* Our Domain Name Server (0 = unknown)*/
-extern IPaddr_t NetOurDNS2IP; /* Our 2nd Domain Name Server (0 = unknown)*/
-extern char NetOurNISDomain[32]; /* Our NIS domain */
-extern char NetOurHostName[32]; /* Our hostname */
-extern char NetOurRootPath[64]; /* Our root path */
-/** END OF BOOTP EXTENTIONS **/
-extern ulong NetBootFileXferSize; /* size of bootfile in bytes */
-extern uchar NetOurEther[6]; /* Our ethernet address */
-extern uchar NetServerEther[6]; /* Boot server enet address */
-extern IPaddr_t NetOurIP; /* Our IP addr (0 = unknown) */
-extern IPaddr_t NetServerIP; /* Server IP addr (0 = unknown) */
-extern uchar * NetTxPacket; /* THE transmit packet */
-extern uchar * NetRxPackets[PKTBUFSRX];/* Receive packets */
-extern uchar * NetRxPkt; /* Current receive packet */
-extern int NetRxPktLen; /* Current rx packet length */
-extern unsigned NetIPID; /* IP ID (counting) */
-extern uchar NetBcastAddr[6]; /* Ethernet boardcast address */
-extern uchar NetEtherNullAddr[6];
-
-#define VLAN_NONE 4095 /* untagged */
-#define VLAN_IDMASK 0x0fff /* mask of valid vlan id */
-extern ushort NetOurVLAN; /* Our VLAN */
-extern ushort NetOurNativeVLAN; /* Our Native VLAN */
-
-extern int NetState; /* Network loop state */
-
-/* ---------- Added by sha ------------ */
-extern IPaddr_t NetArpWaitPacketIP;
-extern uchar *NetArpWaitPacketMAC;
-extern uchar *NetArpWaitTxPacket; /* THE transmit packet */
-extern int NetArpWaitTxPacketSize;
-extern int NetArpWaitTry;
-extern uint64_t NetArpWaitTimerStart;
-extern void ArpRequest (void);
-/* ------------------------------------ */
-
-#define NETLOOP_CONTINUE 1
-#define NETLOOP_SUCCESS 2
-#define NETLOOP_FAIL 3
-
-typedef enum { BOOTP, RARP, ARP, TFTP, DHCP, PING, DNS, NFS, CDP, NETCONS, SNTP } proto_t;
-
-/* Initialize the network adapter */
-int NetLoopInit(proto_t);
-
-/* Do the work */
-int NetLoop(void);
-
-/* Shutdown adapters and cleanup */
-void NetStop(void);
-
-/* Load failed. Start again. */
-void NetStartAgain(void);
-
-/* Get size of the ethernet header when we send */
-int NetEthHdrSize(void);
-
-/* Set ethernet header; returns the size of the header */
-int NetSetEther(uchar *, uchar *, uint);
-
-/* Set IP header */
-void NetSetIP(uchar *, IPaddr_t, int, int, int);
-
-/* Checksum */
-int NetCksumOk(uchar *, int); /* Return true if cksum OK */
-uint NetCksum(uchar *, int); /* Calculate the checksum */
-
-/* Set callbacks */
-void NetSetHandler(rxhand_f *); /* Set RX packet handler */
-void NetSetTimeout(uint64_t, thand_f *);/* Set timeout handler */
-
-/* Transmit "NetTxPacket" */
-void NetSendPacket(uchar *, int);
-
-/* Transmit UDP packet, performing ARP request if needed */
-int NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport, int sport, int len);
-
-/* Processes a received packet */
-void NetReceive(uchar *, int);
-
-/* Print an IP address on the console */
-#ifdef CONFIG_NET
-void print_IPaddr (IPaddr_t);
-#else
-#define print_IPaddr(IPaddr_t);
-#endif
-
-void netboot_update_env(void);
-
-/*
- * The following functions are a bit ugly, but necessary to deal with
- * alignment restrictions on ARM.
- *
- * We're using inline functions, which had the smallest memory
- * footprint in our tests.
- */
-/* return IP *in network byteorder* */
-static inline IPaddr_t NetReadIP(void *from)
-{
- IPaddr_t ip;
- memcpy((void*)&ip, from, sizeof(ip));
- return ip;
-}
-
-/* return ulong *in network byteorder* */
-static inline ulong NetReadLong(ulong *from)
-{
- ulong l;
- memcpy((void*)&l, (void*)from, sizeof(l));
- return l;
-}
-
-/* write IP *in network byteorder* */
-static inline void NetWriteIP(void *to, IPaddr_t ip)
-{
- memcpy(to, (void*)&ip, sizeof(ip));
-}
-
-/* copy IP */
-static inline void NetCopyIP(void *to, void *from)
-{
- memcpy(to, from, sizeof(IPaddr_t));
-}
-
-/* copy ulong */
-static inline void NetCopyLong(ulong *to, ulong *from)
-{
- memcpy((void*)to, (void*)from, sizeof(ulong));
-}
-
-/* Convert an IP address to a string */
-char * ip_to_string (IPaddr_t x, char *s);
-
-/* Convert a string to ip address */
-int string_to_ip(const char *s, IPaddr_t *ip);
-
-/* Convert a VLAN id to a string */
-void VLAN_to_string (ushort x, char *s);
-
-/* Convert a string to a vlan id */
-ushort string_to_VLAN(const char *s);
-
-/* read an IP address from a environment variable */
-IPaddr_t getenv_IPaddr (char *);
-
-/* read a VLAN id from an environment variable */
-ushort getenv_VLAN(char *);
-
-int string_to_ethaddr(const char *str, char *enetaddr);
-void ethaddr_to_string(const unsigned char *enetaddr, char *str);
-
-/**********************************************************************/
-/* Network devices */
-/**********************************************************************/
-
-void eth_set_current(struct eth_device *eth);
-struct eth_device *eth_get_current(void);
-struct eth_device *eth_get_byname(char *name);
-
/*
* Ethernet header
*/
@@ -578,8 +225,6 @@ static inline int net_eth_to_udplen(char *pkt)
int net_checksum_ok(unsigned char *, int); /* Return true if cksum OK */
uint16_t net_checksum(unsigned char *, int); /* Calculate the checksum */
-void NetReceive(unsigned char *, int);
-
/* Print an IP address on the console */
void print_IPaddr (IPaddr_t);
diff --git a/net/net.c b/net/net.c
index 6569b6f..1ae2fb4 100644
--- a/net/net.c
+++ b/net/net.c
@@ -1,73 +1,31 @@
/*
- * Copied from Linux Monitor (LiMon) - Networking.
+ * net.c - barebox networking support
*
- * Copyright 1994 - 2000 Neil Russell.
- * (See License)
- * Copyright 2000 Roland Borde
- * Copyright 2000 Paolo Scaffardi
- * Copyright 2000-2002 Wolfgang Denk, wd@denx.de
- */
-
-/*
- * General Desription:
- *
- * The user interface supports commands for BOOTP, RARP, and TFTP.
- * Also, we support ARP internally. Depending on available data,
- * these interact as follows:
- *
- * BOOTP:
- *
- * Prerequisites: - own ethernet address
- * We want: - own IP address
- * - TFTP server IP address
- * - name of bootfile
- * Next step: ARP
- *
- * RARP:
- *
- * Prerequisites: - own ethernet address
- * We want: - own IP address
- * - TFTP server IP address
- * Next step: ARP
- *
- * ARP:
- *
- * Prerequisites: - own ethernet address
- * - own IP address
- * - TFTP server IP address
- * We want: - TFTP server ethernet address
- * Next step: TFTP
+ * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
*
- * DHCP:
+ * based on U-Boot (LiMon) code
*
- * Prerequisites: - own ethernet address
- * We want: - IP, Netmask, ServerIP, Gateway IP
- * - bootfilename, lease time
- * Next step: - TFTP
+ * Copyright 1994 - 2000 Neil Russell.
+ * Copyright 2000 Roland Borde
+ * Copyright 2000 Paolo Scaffardi
+ * Copyright 2000-2002 Wolfgang Denk, wd@denx.de
*
- * TFTP:
+ * See file CREDITS for list of people who contributed to this
+ * project.
*
- * Prerequisites: - own ethernet address
- * - own IP address
- * - TFTP server IP address
- * - TFTP server ethernet address
- * - name of bootfile (if unknown, we use a default name
- * derived from our own IP address)
- * We want: - load the boot file
- * Next step: none
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
*
- * NFS:
- *
- * Prerequisites: - own ethernet address
- * - own IP address
- * - name of bootfile (if unknown, we use a default name
- * derived from our own IP address)
- * We want: - load the boot file
- * Next step: none
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-
-
#include <common.h>
#include <clock.h>
#include <watchdog.h>
@@ -77,779 +35,58 @@
#include <net.h>
#include <driver.h>
#include <errno.h>
+#include <malloc.h>
#include <init.h>
#include <linux/ctype.h>
#include <linux/err.h>
-#include "tftp.h"
-#include "rarp.h"
-#include "nfs.h"
-
-#define ARP_TIMEOUT (5 * SECOND) /* Seconds before trying ARP again */
-#ifndef CONFIG_NET_RETRY_COUNT
-# define ARP_TIMEOUT_COUNT 5 /* # of timeouts before giving up */
-#else
-# define ARP_TIMEOUT_COUNT (CONFIG_NET_RETRY_COUNT)
-#endif
-
-
-/** BOOTP EXTENTIONS **/
-
-IPaddr_t NetOurSubnetMask=0; /* Our subnet mask (0=unknown) */
-IPaddr_t NetOurGatewayIP=0; /* Our gateways IP address */
-IPaddr_t NetOurDNSIP=0; /* Our DNS IP address */
-#ifdef CONFIG_BOOTP_DNS2
-IPaddr_t NetOurDNS2IP=0; /* Our 2nd DNS IP address */
-#endif
-char NetOurNISDomain[32]={0,}; /* Our NIS domain */
-char NetOurHostName[32]={0,}; /* Our hostname */
-char NetOurRootPath[64]={0,}; /* Our bootpath */
-
-/** END OF BOOTP EXTENTIONS **/
-
-ulong NetBootFileXferSize; /* The actual transferred size of the bootfile (in bytes) */
-uchar NetOurEther[6]; /* Our ethernet address */
-uchar NetServerEther[6] = /* Boot server enet address */
- { 0, 0, 0, 0, 0, 0 };
-IPaddr_t NetOurIP; /* Our IP addr (0 = unknown) */
-IPaddr_t NetServerIP; /* Our IP addr (0 = unknown) */
-uchar *NetRxPkt; /* Current receive packet */
-int NetRxPktLen; /* Current rx packet length */
-unsigned NetIPID; /* IP packet ID */
-uchar NetBcastAddr[6] = /* Ethernet bcast address */
- { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
-uchar NetEtherNullAddr[6] =
- { 0, 0, 0, 0, 0, 0 };
-int NetState; /* Network loop state */
-
-/* XXX in both little & big endian machines 0xFFFF == ntohs(-1) */
-ushort NetOurVLAN = 0xFFFF; /* default is without VLAN */
-ushort NetOurNativeVLAN = 0xFFFF; /* ditto */
-
-char BootFile[128]; /* Boot File name */
-
-uchar PktBuf[(PKTBUFSRX+1) * PKTSIZE_ALIGN + PKTALIGN];
-
-uchar *NetRxPackets[PKTBUFSRX]; /* Receive packets */
-
-static rxhand_f *packetHandler; /* Current RX packet handler */
-static thand_f *timeHandler; /* Current timeout handler */
-static uint64_t timeStart; /* Time base value */
-static uint64_t timeDelta; /* Current timeout value */
-uchar *NetTxPacket = 0; /* THE transmit packet */
-
-static int net_check_prereq (proto_t protocol);
-
-/**********************************************************************/
-
-IPaddr_t NetArpWaitPacketIP;
-IPaddr_t NetArpWaitReplyIP;
-uchar *NetArpWaitPacketMAC; /* MAC address of waiting packet's destination */
-uchar *NetArpWaitTxPacket; /* THE transmit packet */
-int NetArpWaitTxPacketSize;
-uchar NetArpWaitPacketBuf[PKTSIZE_ALIGN + PKTALIGN];
-uint64_t NetArpWaitTimerStart;
-
-void ArpRequest (void)
-{
- int i;
- uchar *pkt;
- ARP_t *arp;
-
- pr_debug("ARP broadcast\n");
-
- pkt = NetTxPacket;
-
- pkt += NetSetEther (pkt, NetBcastAddr, PROT_ARP);
-
- arp = (ARP_t *) pkt;
-
- arp->ar_hrd = htons (ARP_ETHER);
- arp->ar_pro = htons (PROT_IP);
- arp->ar_hln = 6;
- arp->ar_pln = 4;
- arp->ar_op = htons (ARPOP_REQUEST);
-
- memcpy (&arp->ar_data[0], NetOurEther, 6); /* source ET addr */
- NetWriteIP ((uchar *) & arp->ar_data[6], NetOurIP); /* source IP addr */
- for (i = 10; i < 16; ++i) {
- arp->ar_data[i] = 0; /* dest ET addr = 0 */
- }
-
- if ((NetArpWaitPacketIP & NetOurSubnetMask) !=
- (NetOurIP & NetOurSubnetMask)) {
- if (NetOurGatewayIP == 0) {
- puts ("## Warning: gatewayip needed but not set\n");
- NetArpWaitReplyIP = NetArpWaitPacketIP;
- } else {
- NetArpWaitReplyIP = NetOurGatewayIP;
- }
- } else {
- NetArpWaitReplyIP = NetArpWaitPacketIP;
- }
-
- NetWriteIP ((uchar *) & arp->ar_data[16], NetArpWaitReplyIP);
- (void) eth_send (NetTxPacket, (pkt - NetTxPacket) + ARP_HDR_SIZE);
-}
-
-/**********************************************************************/
-/*
- * Main network processing loop.
- */
-
-int NetLoopInit(proto_t protocol)
-{
- struct eth_device *eth_current = eth_get_current();
- IPaddr_t ip;
- int ret;
- int i;
-
- if (!eth_current) {
- printf("Current ethernet device not set!\n");
- return -1;
- }
-
- ip = dev_get_param_ip(ð_current->dev, "ipaddr");
- NetCopyIP(&NetOurIP, &ip);
-
- /* XXX problem with bss workaround */
- NetArpWaitPacketMAC = NULL;
- NetArpWaitTxPacket = NULL;
- NetArpWaitPacketIP = 0;
- NetArpWaitReplyIP = 0;
-
- /*
- * Setup packet buffers, aligned correctly.
- */
- NetTxPacket = &PktBuf[0] + (PKTALIGN - 1);
- NetTxPacket -= (ulong)NetTxPacket % PKTALIGN;
- for (i = 0; i < PKTBUFSRX; i++) {
- NetRxPackets[i] = NetTxPacket + (i+1)*PKTSIZE_ALIGN;
- }
-
- NetArpWaitTxPacket = &NetArpWaitPacketBuf[0] + (PKTALIGN - 1);
- NetArpWaitTxPacket -= (ulong)NetArpWaitTxPacket % PKTALIGN;
- NetArpWaitTxPacketSize = 0;
-
- string_to_ethaddr(dev_get_param(ð_get_current()->dev, "ethaddr"),
- NetOurEther);
-
- NetState = NETLOOP_CONTINUE;
-
- NetOurGatewayIP = dev_get_param_ip(ð_current->dev, "gateway");
- NetOurSubnetMask = dev_get_param_ip(ð_current->dev, "netmask");
- NetOurVLAN = getenv_VLAN("vlan");
- NetOurNativeVLAN = getenv_VLAN("nvlan");
- NetServerIP = dev_get_param_ip(ð_current->dev, "serverip");
-
- ret = net_check_prereq(protocol);
-
- return ret;
-}
-
-int NetLoop(void)
-{
- /*
- * Start the ball rolling with the given start function. From
- * here on, this code is a state machine driven by received
- * packets and timer events.
- */
-
- NetBootFileXferSize = 0;
-
- /*
- * Main packet reception loop. Loop receiving packets until
- * someone sets `NetState' to a state that terminates.
- */
- for (;;) {
- WATCHDOG_RESET();
-#ifdef CONFIG_SHOW_ACTIVITY
- {
- extern void show_activity(int arg);
- show_activity(1);
- }
-#endif
- /*
- * Check the ethernet for a new packet. The ethernet
- * receive routine will process it.
- */
- eth_rx();
-
- /*
- * Abort if ctrl-c was pressed.
- */
- if (ctrlc()) {
- puts ("\nAbort\n");
- return -1;
- }
-
- /* check for arp timeout */
- if (NetArpWaitPacketIP &&
- is_timeout(NetArpWaitTimerStart, ARP_TIMEOUT)) {
- NetArpWaitTimerStart = get_time_ns();
- ArpRequest();
- }
-
- /*
- * Check for a timeout, and run the timeout handler
- * if we have one.
- */
- if (timeHandler && is_timeout(timeStart, timeDelta)) {
- thand_f *x;
- x = timeHandler;
- timeHandler = (thand_f *)0;
- (*x)();
- }
-
- switch (NetState) {
- case NETLOOP_SUCCESS:
- if (NetBootFileXferSize > 0) {
- char buf[10];
- printf("Bytes transferred = %ld (%lx hex)\n",
- NetBootFileXferSize,
- NetBootFileXferSize);
- sprintf(buf, "0x%lx", NetBootFileXferSize);
- setenv("filesize", buf);
- }
- return NetBootFileXferSize;
-
- case NETLOOP_FAIL:
- return -1;
- }
- }
-}
-
-/**********************************************************************/
-/*
- * Miscelaneous bits.
- */
-
-void
-NetSetHandler(rxhand_f * f)
-{
- packetHandler = f;
-}
-
-
-void
-NetSetTimeout(uint64_t iv, thand_f * f)
-{
- if (iv == 0) {
- timeHandler = (thand_f *)0;
- } else {
- timeHandler = f;
- timeStart = get_time_ns();
- timeDelta = iv;
- }
-}
-
-
-void
-NetSendPacket(uchar * pkt, int len)
-{
- (void) eth_send(pkt, len);
-}
-
-int
-NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport, int sport, int len)
-{
- uchar *pkt;
-
- /* convert to new style broadcast */
- if (dest == 0)
- dest = 0xFFFFFFFF;
-
- /* if broadcast, make the ether address a broadcast and don't do ARP */
- if (dest == 0xFFFFFFFF)
- ether = NetBcastAddr;
-
- /* if MAC address was not discovered yet, save the packet and do an ARP request */
- if (memcmp(ether, NetEtherNullAddr, 6) == 0) {
- pr_debug("sending ARP for %08lx\n", dest);
-
- NetArpWaitPacketIP = dest;
- NetArpWaitPacketMAC = ether;
-
- pkt = NetArpWaitTxPacket;
- pkt += NetSetEther (pkt, NetArpWaitPacketMAC, PROT_IP);
-
- NetSetIP (pkt, dest, dport, sport, len);
- memcpy(pkt + IP_HDR_SIZE, (uchar *)NetTxPacket + (pkt - (uchar *)NetArpWaitTxPacket) + IP_HDR_SIZE, len);
-
- /* size of the waiting packet */
- NetArpWaitTxPacketSize = (pkt - NetArpWaitTxPacket) + IP_HDR_SIZE + len;
-
- /* and do the ARP request */
- NetArpWaitTimerStart = get_time_ns();
- ArpRequest();
- return 1; /* waiting */
- }
-
- pr_debug("sending UDP to %08lx/%02x:%02x:%02x:%02x:%02x:%02x\n",
- dest, ether[0], ether[1], ether[2], ether[3], ether[4], ether[5]);
+static IPaddr_t net_netmask; /* Our subnet mask (0=unknown) */
+static IPaddr_t net_gateway; /* Our gateways IP address */
+static IPaddr_t net_dns_server; /* Our DNS IP address */
- pkt = (uchar *)NetTxPacket;
- pkt += NetSetEther (pkt, ether, PROT_IP);
- NetSetIP (pkt, dest, dport, sport, len);
- (void) eth_send(NetTxPacket, (pkt - NetTxPacket) + IP_HDR_SIZE + len);
+static unsigned char net_ether[6]; /* Our ethernet address */
+static IPaddr_t net_ip; /* Our IP addr (0 = unknown) */
+static IPaddr_t net_serverip; /* Our IP addr (0 = unknown) */
- return 0; /* transmitted */
-}
+unsigned char *NetRxPackets[PKTBUFSRX]; /* Receive packets */
+static unsigned int net_ip_id;
-void
-NetReceive(uchar * inpkt, int len)
+void net_update_env(void)
{
- Ethernet_t *et;
- IP_t *ip;
- ARP_t *arp;
- IPaddr_t tmp;
- int x;
- uchar *pkt;
- ushort cti = 0, vlanid = VLAN_NONE, myvlanid, mynvlanid;
-
- pr_debug("packet received\n");
-
- if (!net_receive(inpkt, len))
- return;
-
- NetRxPkt = inpkt;
- NetRxPktLen = len;
- et = (Ethernet_t *)inpkt;
-
- /* too small packet? */
- if (len < ETHER_HDR_SIZE)
- return;
-
- myvlanid = ntohs(NetOurVLAN);
- if (myvlanid == (ushort)-1)
- myvlanid = VLAN_NONE;
- mynvlanid = ntohs(NetOurNativeVLAN);
- if (mynvlanid == (ushort)-1)
- mynvlanid = VLAN_NONE;
-
- x = ntohs(et->et_protlen);
-
- pr_debug("packet received\n");
-
- if (x < 1514) {
- /*
- * Got a 802 packet. Check the other protocol field.
- */
- x = ntohs(et->et_prot);
-
- ip = (IP_t *)(inpkt + E802_HDR_SIZE);
- len -= E802_HDR_SIZE;
-
- } else if (x != PROT_VLAN) { /* normal packet */
- ip = (IP_t *)(inpkt + ETHER_HDR_SIZE);
- len -= ETHER_HDR_SIZE;
-
- } else { /* VLAN packet */
- VLAN_Ethernet_t *vet = (VLAN_Ethernet_t *)et;
-
- pr_debug("VLAN packet received\n");
-
- /* too small packet? */
- if (len < VLAN_ETHER_HDR_SIZE)
- return;
-
- /* if no VLAN active */
- if ((ntohs(NetOurVLAN) & VLAN_IDMASK) == VLAN_NONE
- )
- return;
-
- cti = ntohs(vet->vet_tag);
- vlanid = cti & VLAN_IDMASK;
- x = ntohs(vet->vet_type);
-
- ip = (IP_t *)(inpkt + VLAN_ETHER_HDR_SIZE);
- len -= VLAN_ETHER_HDR_SIZE;
- }
-
- pr_debug("Receive from protocol 0x%x\n", x);
-
- if ((myvlanid & VLAN_IDMASK) != VLAN_NONE) {
- if (vlanid == VLAN_NONE)
- vlanid = (mynvlanid & VLAN_IDMASK);
- /* not matched? */
- if (vlanid != (myvlanid & VLAN_IDMASK))
- return;
- }
-
- switch (x) {
-
- case PROT_ARP:
- /*
- * We have to deal with two types of ARP packets:
- * - REQUEST packets will be answered by sending our
- * IP address - if we know it.
- * - REPLY packets are expected only after we asked
- * for the TFTP server's or the gateway's ethernet
- * address; so if we receive such a packet, we set
- * the server ethernet address
- */
- pr_debug("Got ARP\n");
-
- arp = (ARP_t *)ip;
- if (len < ARP_HDR_SIZE) {
- printf("bad length %d < %d\n", len, ARP_HDR_SIZE);
- return;
- }
- if (ntohs(arp->ar_hrd) != ARP_ETHER) {
- return;
- }
- if (ntohs(arp->ar_pro) != PROT_IP) {
- return;
- }
- if (arp->ar_hln != 6) {
- return;
- }
- if (arp->ar_pln != 4) {
- return;
- }
-
- if (NetOurIP == 0) {
- return;
- }
-
- if (NetReadIP(&arp->ar_data[16]) != NetOurIP) {
- return;
- }
-
- switch (ntohs(arp->ar_op)) {
- case ARPOP_REQUEST: /* reply with our IP address */
- pr_debug("Got ARP REQUEST, return our IP\n");
-
- pkt = (uchar *)et;
- pkt += NetSetEther(pkt, et->et_src, PROT_ARP);
- arp->ar_op = htons(ARPOP_REPLY);
- memcpy (&arp->ar_data[10], &arp->ar_data[0], 6);
- NetCopyIP(&arp->ar_data[16], &arp->ar_data[6]);
- memcpy (&arp->ar_data[ 0], NetOurEther, 6);
- NetCopyIP(&arp->ar_data[ 6], &NetOurIP);
- memcpy(NetTxPacket, et, (pkt - (uchar *)et) + ARP_HDR_SIZE);
- eth_send((uchar *)NetTxPacket, (pkt - (uchar *)et) + ARP_HDR_SIZE);
- return;
-
- case ARPOP_REPLY: /* arp reply */
- /* are we waiting for a reply */
- if (!NetArpWaitPacketIP || !NetArpWaitPacketMAC)
- break;
- pr_debug("Got ARP REPLY, set server/gtwy eth addr (%02x:%02x:%02x:%02x:%02x:%02x)\n",
- arp->ar_data[0], arp->ar_data[1],
- arp->ar_data[2], arp->ar_data[3],
- arp->ar_data[4], arp->ar_data[5]);
-
- tmp = NetReadIP(&arp->ar_data[6]);
-
- /* matched waiting packet's address */
- if (tmp == NetArpWaitReplyIP) {
- pr_debug("Got it\n");
-
- /* save address for later use */
- memcpy(NetArpWaitPacketMAC, &arp->ar_data[0], 6);
-
- /* modify header, and transmit it */
- memcpy(((Ethernet_t *)NetArpWaitTxPacket)->et_dest, NetArpWaitPacketMAC, 6);
- (void) eth_send(NetArpWaitTxPacket, NetArpWaitTxPacketSize);
-
- /* no arp request pending now */
- NetArpWaitPacketIP = 0;
- NetArpWaitTxPacketSize = 0;
- NetArpWaitPacketMAC = NULL;
-
- }
- return;
- default:
- pr_debug("Unexpected ARP opcode 0x%x\n", ntohs(arp->ar_op));
- return;
- }
- break;
-
- case PROT_RARP:
- pr_debug("Got RARP\n");
-
- arp = (ARP_t *)ip;
- if (len < ARP_HDR_SIZE) {
- printf("bad length %d < %d\n", len, ARP_HDR_SIZE);
- return;
- }
-
- if ((ntohs(arp->ar_op) != RARPOP_REPLY) ||
- (ntohs(arp->ar_hrd) != ARP_ETHER) ||
- (ntohs(arp->ar_pro) != PROT_IP) ||
- (arp->ar_hln != 6) || (arp->ar_pln != 4)) {
-
- puts ("invalid RARP header\n");
- } else {
- NetCopyIP(&NetOurIP, &arp->ar_data[16]);
- if (NetServerIP == 0)
- NetCopyIP(&NetServerIP, &arp->ar_data[ 6]);
- memcpy (NetServerEther, &arp->ar_data[ 0], 6);
-
- if (packetHandler)
- (*packetHandler)(0,0,0,0);
- }
- break;
-
- case PROT_IP:
- pr_debug("Got IP\n");
-
- if (len < IP_HDR_SIZE) {
- debug ("len bad %d < %d\n", len, IP_HDR_SIZE);
- return;
- }
- if (len < ntohs(ip->ip_len)) {
- printf("len bad %d < %d\n", len, ntohs(ip->ip_len));
- return;
- }
- len = ntohs(ip->ip_len);
-
- pr_debug("len=%d, v=%02x\n", len, ip->ip_hl_v & 0xff);
+ struct eth_device *edev = eth_get_current();
- if ((ip->ip_hl_v & 0xf0) != 0x40) {
- return;
- }
- if (ip->ip_off & htons(0x1fff)) { /* Can't deal w/ fragments */
- return;
- }
- if (!NetCksumOk((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2)) {
- puts ("checksum bad\n");
- return;
- }
- tmp = NetReadIP(&ip->ip_dst);
- if (NetOurIP && tmp != NetOurIP && tmp != 0xFFFFFFFF) {
- return;
- }
- /*
- * watch for ICMP host redirects
- *
- * There is no real handler code (yet). We just watch
- * for ICMP host redirect messages. In case anybody
- * sees these messages: please contact me
- * (wd@denx.de), or - even better - send me the
- * necessary fixes :-)
- *
- * Note: in all cases where I have seen this so far
- * it was a problem with the router configuration,
- * for instance when a router was configured in the
- * BOOTP reply, but the TFTP server was on the same
- * 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.
- */
- if (ip->ip_p == IPPROTO_ICMP) {
- ICMP_t *icmph = (ICMP_t *)&(ip->udp_src);
-
- switch (icmph->type) {
- case ICMP_REDIRECT:
- if (icmph->code != ICMP_REDIR_HOST)
- return;
- puts (" ICMP Host Redirect to ");
- print_IPaddr(icmph->un.gateway);
- putchar(' ');
- return;
-#ifdef CONFIG_NET_PING
- case ICMP_ECHO_REPLY:
- /*
- * IP header OK. Pass the packet to the current handler.
- */
- /* XXX point to ip packet */
- if (packetHandler)
- (*packetHandler)((uchar *)ip, 0, 0, 0);
- return;
-#endif
- default:
- return;
- }
- } else if (ip->ip_p != IPPROTO_UDP) { /* Only UDP packets */
- return;
- }
+ net_ip = dev_get_param_ip(&edev->dev, "ipaddr");
+ net_serverip = dev_get_param_ip(&edev->dev, "serverip");
+ net_gateway = dev_get_param_ip(&edev->dev, "gateway");
+ net_netmask = dev_get_param_ip(&edev->dev, "netmask");
-#ifdef CONFIG_UDP_CHECKSUM
- if (ip->udp_xsum != 0) {
- ulong xsum;
- ushort *sumptr;
- ushort sumlen;
-
- xsum = ip->ip_p;
- xsum += (ntohs(ip->udp_len));
- xsum += (ntohl(ip->ip_src) >> 16) & 0x0000ffff;
- xsum += (ntohl(ip->ip_src) >> 0) & 0x0000ffff;
- xsum += (ntohl(ip->ip_dst) >> 16) & 0x0000ffff;
- xsum += (ntohl(ip->ip_dst) >> 0) & 0x0000ffff;
-
- sumlen = ntohs(ip->udp_len);
- sumptr = (ushort *) &(ip->udp_src);
-
- while (sumlen > 1) {
- ushort sumdata;
-
- sumdata = *sumptr++;
- xsum += ntohs(sumdata);
- sumlen -= 2;
- }
- if (sumlen > 0) {
- ushort sumdata;
-
- sumdata = *(unsigned char *) sumptr;
- sumdata = (sumdata << 8) & 0xff00;
- xsum += sumdata;
- }
- while ((xsum >> 16) != 0) {
- xsum = (xsum & 0x0000ffff) + ((xsum >> 16) & 0x0000ffff);
- }
- if ((xsum != 0x00000000) && (xsum != 0x0000ffff)) {
- printf(" UDP wrong checksum %08x %08x\n", xsum, ntohs(ip->udp_xsum));
- return;
- }
- }
-#endif
- /*
- * IP header OK. Pass the packet to the current handler.
- */
- if (packetHandler)
- (*packetHandler)((uchar *)ip +IP_HDR_SIZE,
- ntohs(ip->udp_dst),
- ntohs(ip->udp_src),
- ntohs(ip->udp_len) - 8);
- break;
- }
+ string_to_ethaddr(dev_get_param(&edev->dev, "ethaddr"),
+ net_ether);
}
-
-/**********************************************************************/
-
-static int net_check_prereq (proto_t protocol)
+int net_checksum_ok(unsigned char *ptr, int len)
{
- struct eth_device *edev = eth_get_current();
-
- switch (protocol) {
- /* Fall through */
-#ifdef CONFIG_NET_NFS
- case NFS:
-#endif
- case NETCONS:
- case TFTP:
- if (NetServerIP == 0) {
- printf("*** ERROR: `%s.serverip' not set\n", dev_id(&edev->dev));
- return -1;
- }
-
- if (NetOurIP == 0) {
- printf("*** ERROR: `%s.ipaddr' not set\n", dev_id(&edev->dev));
- return -1;
- }
- /* Fall through */
-
- case DHCP:
- case RARP:
- case BOOTP:
- if (memcmp (NetOurEther, "\0\0\0\0\0\0", 6) == 0) {
- printf("*** ERROR: `%s.ethaddr' not set\n", dev_id(&edev->dev));
- return -1;
- }
- /* Fall through */
- default:
- return 0;
- }
-
- return -1; /* not reached */
+ return net_checksum(ptr, len) + 1;
}
-/**********************************************************************/
-int
-NetCksumOk(uchar * ptr, int len)
+uint16_t net_checksum(unsigned char *ptr, int len)
{
- return !((NetCksum(ptr, len) + 1) & 0xfffe);
-}
+ uint32_t xsum = 0;
+ uint16_t *p = (uint16_t *)ptr;
+ if (len & 1)
+ ptr[len] = 0;
-unsigned
-NetCksum(uchar * ptr, int len)
-{
- ulong xsum;
- ushort *p = (ushort *)ptr;
+ len = (len + 1) >> 1;
- xsum = 0;
while (len-- > 0)
xsum += *p++;
+
xsum = (xsum & 0xffff) + (xsum >> 16);
xsum = (xsum & 0xffff) + (xsum >> 16);
return xsum & 0xffff;
}
-int
-NetEthHdrSize(void)
-{
- ushort myvlanid;
-
- myvlanid = ntohs(NetOurVLAN);
- if (myvlanid == (ushort)-1)
- myvlanid = VLAN_NONE;
-
- return ((myvlanid & VLAN_IDMASK) == VLAN_NONE) ? ETHER_HDR_SIZE : VLAN_ETHER_HDR_SIZE;
-}
-
-int
-NetSetEther(uchar * xet, uchar * addr, uint prot)
-{
- Ethernet_t *et = (Ethernet_t *)xet;
- ushort myvlanid;
-
- myvlanid = ntohs(NetOurVLAN);
- if (myvlanid == (ushort)-1)
- myvlanid = VLAN_NONE;
-
- memcpy (et->et_dest, addr, 6);
- memcpy (et->et_src, NetOurEther, 6);
- if ((myvlanid & VLAN_IDMASK) == VLAN_NONE) {
- et->et_protlen = htons(prot);
- return ETHER_HDR_SIZE;
- } else {
- VLAN_Ethernet_t *vet = (VLAN_Ethernet_t *)xet;
-
- vet->vet_vlan_type = htons(PROT_VLAN);
- vet->vet_tag = htons((0 << 5) | (myvlanid & VLAN_IDMASK));
- vet->vet_type = htons(prot);
- return VLAN_ETHER_HDR_SIZE;
- }
-}
-
-void
-NetSetIP(uchar * xip, IPaddr_t dest, int dport, int sport, int len)
-{
- IP_t *ip = (IP_t *)xip;
-
- /*
- * If the data is an odd number of bytes, zero the
- * byte after the last byte so that the checksum
- * will work.
- */
- if (len & 1)
- xip[IP_HDR_SIZE + len] = 0;
-
- /*
- * Construct an IP and UDP header.
- * (need to set no fragment bit - XXX)
- */
- ip->ip_hl_v = 0x45; /* IP_HDR_SIZE / 4 (not including UDP) */
- ip->ip_tos = 0;
- ip->ip_len = htons(IP_HDR_SIZE + len);
- ip->ip_id = htons(NetIPID++);
- ip->ip_off = htons(0x4000); /* No fragmentation */
- ip->ip_ttl = 255;
- ip->ip_p = 17; /* UDP */
- ip->ip_sum = 0;
- NetCopyIP((void*)&ip->ip_src, &NetOurIP); /* already in network byte order */
- NetCopyIP((void*)&ip->ip_dst, &dest); /* - "" - */
- ip->udp_src = htons(sport);
- ip->udp_dst = htons(dport);
- ip->udp_len = htons(8 + len);
- ip->udp_xsum = 0;
- ip->ip_sum = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2);
-}
-
char *ip_to_string (IPaddr_t x, char *s)
{
x = ntohl (x);
@@ -871,7 +108,7 @@ int string_to_ip(const char *s, IPaddr_t *ip)
return -EINVAL;
for (i = 0; i < 4; i++) {
- ulong val;
+ unsigned long val;
if (!isdigit(*s))
return -EINVAL;
@@ -890,34 +127,6 @@ int string_to_ip(const char *s, IPaddr_t *ip)
return 0;
}
-void VLAN_to_string(ushort x, char *s)
-{
- x = ntohs(x);
-
- if (x == (ushort)-1)
- x = VLAN_NONE;
-
- if (x == VLAN_NONE)
- strcpy(s, "none");
- else
- sprintf(s, "%d", x & VLAN_IDMASK);
-}
-
-ushort string_to_VLAN(const char *s)
-{
- ushort id;
-
- if (s == NULL)
- return htons(VLAN_NONE);
-
- if (*s < '0' || *s > '9')
- id = VLAN_NONE;
- else
- id = (ushort)simple_strtoul(s, NULL, 10);
-
- return htons(id);
-}
-
void print_IPaddr (IPaddr_t x)
{
char tmp[16];
@@ -927,14 +136,9 @@ void print_IPaddr (IPaddr_t x)
puts (tmp);
}
-ushort getenv_VLAN(char *var)
-{
- return string_to_VLAN(getenv(var));
-}
-
int string_to_ethaddr(const char *str, char *enetaddr)
{
- ulong reg;
+ int reg;
char *e;
if (!str || strlen(str) != 17)
@@ -954,66 +158,11 @@ int string_to_ethaddr(const char *str, char *enetaddr)
void ethaddr_to_string(const unsigned char *enetaddr, char *str)
{
- sprintf (str, "%02X:%02X:%02X:%02X:%02X:%02X",
+ sprintf(str, "%02X:%02X:%02X:%02X:%02X:%02X",
enetaddr[0], enetaddr[1], enetaddr[2], enetaddr[3],
enetaddr[4], enetaddr[5]);
}
-static IPaddr_t net_netmask; /* Our subnet mask (0=unknown) */
-static IPaddr_t net_gateway; /* Our gateways IP address */
-static IPaddr_t net_dns_server; /* Our DNS IP address */
-
-static unsigned char net_ether[6]; /* Our ethernet address */
-static IPaddr_t net_ip; /* Our IP addr (0 = unknown) */
-static IPaddr_t net_serverip; /* Our IP addr (0 = unknown) */
-
-unsigned char *NetRxPackets[PKTBUFSRX]; /* Receive packets */
-static unsigned int net_ip_id;
-
-void net_update_env(void)
-{
- struct eth_device *edev = eth_get_current();
-
- net_ip = dev_get_param_ip(&edev->dev, "ipaddr");
- net_serverip = dev_get_param_ip(&edev->dev, "serverip");
- net_gateway = dev_get_param_ip(&edev->dev, "gateway");
- net_netmask = dev_get_param_ip(&edev->dev, "netmask");
-
- string_to_ethaddr(dev_get_param(&edev->dev, "ethaddr"),
- net_ether);
-
- NetOurIP = dev_get_param_ip(&edev->dev, "ipaddr");
- NetServerIP = dev_get_param_ip(&edev->dev, "serverip");
- NetOurGatewayIP = dev_get_param_ip(&edev->dev, "gateway");
- NetOurSubnetMask = dev_get_param_ip(&edev->dev, "netmask");
-
- string_to_ethaddr(dev_get_param(&edev->dev, "ethaddr"),
- NetOurEther);
-}
-
-int net_checksum_ok(unsigned char *ptr, int len)
-{
- return net_checksum(ptr, len) + 1;
-}
-
-uint16_t net_checksum(unsigned char *ptr, int len)
-{
- uint32_t xsum = 0;
- uint16_t *p = (uint16_t *)ptr;
-
- if (len & 1)
- ptr[len] = 0;
-
- len = (len + 1) >> 1;
-
- while (len-- > 0)
- xsum += *p++;
-
- xsum = (xsum & 0xffff) + (xsum >> 16);
- xsum = (xsum & 0xffff) + (xsum >> 16);
- return xsum & 0xffff;
-}
-
static unsigned char *arp_ether;
static IPaddr_t arp_wait_ip;
--
1.7.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 11/13] rework device parameters
2010-06-04 9:54 reworking the network stack Sascha Hauer
` (9 preceding siblings ...)
2010-06-04 9:55 ` [PATCH 10/13] net: remove old network stack Sascha Hauer
@ 2010-06-04 9:55 ` Sascha Hauer
2010-06-04 9:55 ` [PATCH 12/13] errno: add strings for network related error messages Sascha Hauer
2010-06-04 9:55 ` [PATCH 13/13] add netconsole support Sascha Hauer
12 siblings, 0 replies; 18+ messages in thread
From: Sascha Hauer @ 2010-06-04 9:55 UTC (permalink / raw)
To: barebox
Change device parameters so that the memory management is in generic
code. This also removes the need of storing statically initialized
parameters as they are stored in a struct list_head for each device.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
common/console.c | 40 ++++++-----
drivers/nand/nand.c | 7 +-
drivers/video/fb.c | 21 +++---
drivers/video/imx.c | 17 +++--
include/console.h | 6 --
include/driver.h | 2 +-
include/fb.h | 2 -
include/net.h | 6 --
include/param.h | 15 ++++-
lib/driver.c | 12 +--
lib/parameter.c | 195 ++++++++++++++++++++++++++++++++-------------------
net/eth.c | 48 ++++---------
12 files changed, 201 insertions(+), 170 deletions(-)
diff --git a/common/console.c b/common/console.c
index d3d31f7..7199d9a 100644
--- a/common/console.c
+++ b/common/console.c
@@ -57,26 +57,32 @@ static int console_std_set(struct device_d *dev, struct param_d *param,
const char *val)
{
struct console_device *cdev = dev->type_data;
+ char active[4];
unsigned int flag = 0, i = 0;
+ if (!val)
+ dev_param_set_generic(dev, param, NULL);
+
if (strchr(val, 'i') && cdev->f_caps & CONSOLE_STDIN) {
- cdev->active[i++] = 'i';
+ active[i++] = 'i';
flag |= CONSOLE_STDIN;
}
if (strchr(val, 'o') && cdev->f_caps & CONSOLE_STDOUT) {
- cdev->active[i++] = 'o';
+ active[i++] = 'o';
flag |= CONSOLE_STDOUT;
}
if (strchr(val, 'e') && cdev->f_caps & CONSOLE_STDERR) {
- cdev->active[i++] = 'e';
+ active[i++] = 'e';
flag |= CONSOLE_STDERR;
}
- cdev->active[i] = 0;
+ active[i] = 0;
cdev->f_active = flag;
+ dev_param_set_generic(dev, param, active);
+
return 0;
}
@@ -85,8 +91,12 @@ static int console_baudrate_set(struct device_d *dev, struct param_d *param,
{
struct console_device *cdev = dev->type_data;
int baudrate;
+ char baudstr[16];
unsigned char c;
+ if (!val)
+ dev_param_set_generic(dev, param, NULL);
+
baudrate = simple_strtoul(val, NULL, 10);
if (cdev->f_active) {
@@ -101,7 +111,8 @@ static int console_baudrate_set(struct device_d *dev, struct param_d *param,
} else
cdev->setbrg(cdev, baudrate);
- sprintf(cdev->baudrate_string, "%d", baudrate);
+ sprintf(baudstr, "%d", baudrate);
+ dev_param_set_generic(dev, param, baudstr);
return 0;
}
@@ -129,29 +140,20 @@ int console_register(struct console_device *newcdev)
register_device(dev);
if (newcdev->setbrg) {
- newcdev->baudrate_param.set = console_baudrate_set;
- newcdev->baudrate_param.name = "baudrate";
- sprintf(newcdev->baudrate_string, "%d",
- CONFIG_BAUDRATE);
- console_baudrate_set(dev, &newcdev->baudrate_param,
- newcdev->baudrate_string);
- newcdev->baudrate_param.value = newcdev->baudrate_string;
- dev_add_param(dev, &newcdev->baudrate_param);
+ dev_add_param(dev, "baudrate", console_baudrate_set, NULL, 0);
+ dev_set_param(dev, "baudrate", "115200");
}
- newcdev->active_param.set = console_std_set;
- newcdev->active_param.name = "active";
- newcdev->active_param.value = newcdev->active;
- dev_add_param(dev, &newcdev->active_param);
+ dev_add_param(dev, "active", console_std_set, NULL, 0);
initialized = CONSOLE_INIT_FULL;
#ifdef CONFIG_CONSOLE_ACTIVATE_ALL
- console_std_set(dev, &newcdev->active_param, "ioe");
+ dev_set_param(dev, "active", "ioe");
#endif
#ifdef CONFIG_CONSOLE_ACTIVATE_FIRST
if (list_empty(&console_list)) {
first = 1;
- console_std_set(dev, &newcdev->active_param, "ioe");
+ dev_set_param(dev, "active", "ioe");
}
#endif
diff --git a/drivers/nand/nand.c b/drivers/nand/nand.c
index bcf52bd..4927231 100644
--- a/drivers/nand/nand.c
+++ b/drivers/nand/nand.c
@@ -210,6 +210,7 @@ static struct file_operations nand_ops_oob = {
int add_mtd_device(struct mtd_info *mtd)
{
struct nand_chip *chip = mtd->priv;
+ char str[16];
strcpy(mtd->class_dev.name, "nand");
register_device(&mtd->class_dev);
@@ -220,10 +221,8 @@ int add_mtd_device(struct mtd_info *mtd)
mtd->cdev.priv = mtd;
mtd->cdev.dev = &mtd->class_dev;
- mtd->param_size.flags = PARAM_FLAG_RO;
- mtd->param_size.name = "size";
- mtd->param_size.value = asprintf("%u", mtd->size);
- dev_add_param(&mtd->class_dev, &mtd->param_size);
+ sprintf(str, "%u", mtd->size);
+ dev_add_param_fixed(&mtd->class_dev, "size", str);
devfs_create(&mtd->cdev);
diff --git a/drivers/video/fb.c b/drivers/video/fb.c
index 00a0f6a..841c3af 100644
--- a/drivers/video/fb.c
+++ b/drivers/video/fb.c
@@ -32,15 +32,22 @@ static int fb_enable_set(struct device_d *dev, struct param_d *param,
{
struct fb_info *info = dev->priv;
int enable;
+ char *new;
+
+ if (!val)
+ return dev_param_set_generic(dev, param, NULL);
enable = simple_strtoul(val, NULL, 0);
- if (enable)
+ if (enable) {
info->fbops->fb_enable(info);
- else
+ new = "1";
+ } else {
info->fbops->fb_disable(info);
+ new = "0";
+ }
- sprintf(info->enable_string, "%d", !!enable);
+ dev_param_set_generic(dev, param, new);
return 0;
}
@@ -71,13 +78,9 @@ int register_framebuffer(struct fb_info *info)
sprintf(dev->name, "fb");
- info->param_enable.set = fb_enable_set;
- info->param_enable.name = "enable";
- sprintf(info->enable_string, "%d", 0);
- info->param_enable.value = info->enable_string;
- dev_add_param(dev, &info->param_enable);
-
register_device(&info->dev);
+ dev_add_param(dev, "enable", fb_enable_set, NULL, 0);
+ dev_set_param(dev, "enable", "0");
devfs_create(&info->cdev);
diff --git a/drivers/video/imx.c b/drivers/video/imx.c
index 67cae34..d9ba643 100644
--- a/drivers/video/imx.c
+++ b/drivers/video/imx.c
@@ -154,8 +154,6 @@ struct imxfb_info {
struct fb_info overlay;
- struct param_d param_alpha;
- char alpha_string[4];
};
#define IMX_NAME "IMX"
@@ -427,8 +425,12 @@ static int imxfb_alpha_set(struct device_d *dev, struct param_d *param,
struct fb_info *overlay = dev->priv;
struct imxfb_info *fbi = overlay->priv;
int alpha;
+ char alphastr[16];
unsigned int tmp;
+ if (!val)
+ return dev_param_set_generic(dev, param, NULL);
+
alpha = simple_strtoul(val, NULL, 0);
alpha &= 0xff;
@@ -437,7 +439,9 @@ static int imxfb_alpha_set(struct device_d *dev, struct param_d *param,
tmp |= LGWCR_GWAV(alpha);
writel(tmp , fbi->regs + LCDC_LGWCR);
- sprintf(fbi->alpha_string, "%d", alpha);
+ sprintf(alphastr, "%d", alpha);
+
+ dev_param_set_generic(dev, param, alphastr);
return 0;
}
@@ -502,11 +506,8 @@ static int imxfb_register_overlay(struct imxfb_info *fbi, void *fb)
return ret;
}
- fbi->param_alpha.set = imxfb_alpha_set;
- fbi->param_alpha.name = "alpha";
- sprintf(fbi->alpha_string, "%d", 0);
- fbi->param_alpha.value = fbi->alpha_string;
- dev_add_param(&overlay->dev, &fbi->param_alpha);
+ dev_add_param(&overlay->dev, "alpha", imxfb_alpha_set, NULL, 0);
+ dev_set_param(&overlay->dev, "alpha", "0");
return 0;
}
diff --git a/include/console.h b/include/console.h
index 3568c56..3bcc5db 100644
--- a/include/console.h
+++ b/include/console.h
@@ -46,12 +46,6 @@ struct console_device {
unsigned char f_caps;
unsigned char f_active;
-
- struct param_d baudrate_param;
- char baudrate_string[8];
-
- struct param_d active_param;
- char active[4];
};
int console_register(struct console_device *cdev);
diff --git a/include/driver.h b/include/driver.h
index 1dde38e..6950c02 100644
--- a/include/driver.h
+++ b/include/driver.h
@@ -98,7 +98,7 @@ struct device_d {
/*! The parameters for this device. This is used to carry information
* of board specific data from the board code to the device driver. */
- struct param_d *param;
+ struct list_head parameters;
struct list_head cdevs;
};
diff --git a/include/fb.h b/include/fb.h
index f213c42..218500b 100644
--- a/include/fb.h
+++ b/include/fb.h
@@ -80,8 +80,6 @@ struct fb_info {
struct fb_ops *fbops;
struct device_d dev; /* This is this fb device */
- struct param_d param_enable;
- char enable_string[1];
void *screen_base;
diff --git a/include/net.h b/include/net.h
index 627b18b..f0321a7 100644
--- a/include/net.h
+++ b/include/net.h
@@ -41,12 +41,6 @@ struct eth_device {
struct eth_device *next;
void *priv;
- struct param_d param_ip;
- struct param_d param_netmask;
- struct param_d param_gateway;
- struct param_d param_serverip;
- struct param_d param_ethaddr;
-
struct device_d dev;
struct list_head list;
diff --git a/include/param.h b/include/param.h
index fe4468e..207ad50 100644
--- a/include/param.h
+++ b/include/param.h
@@ -2,6 +2,7 @@
#define PARAM_H
#include <linux/types.h>
+#include <linux/list.h>
#define PARAM_FLAG_RO (1 << 0)
@@ -15,12 +16,24 @@ struct param_d {
char *name;
struct param_d *next;
char *value;
+ struct list_head list;
};
const char *dev_get_param(struct device_d *dev, const char *name);
int dev_set_param(struct device_d *dev, const char *name, const char *val);
struct param_d *get_param_by_name(struct device_d *dev, const char *name);
-int dev_add_param(struct device_d *dev, struct param_d *par);
+
+int dev_add_param(struct device_d *dev, char *name,
+ int (*set)(struct device_d *dev, struct param_d *p, const char *val),
+ char *(*get)(struct device_d *, struct param_d *p),
+ unsigned long flags);
+
+int dev_add_param_fixed(struct device_d *dev, char *name, char *value);
+
+void dev_remove_parameters(struct device_d *dev);
+
+int dev_param_set_generic(struct device_d *dev, struct param_d *p,
+ const char *val);
/* Convenience functions to handle a parameter as an ip address */
int dev_set_param_ip(struct device_d *dev, char *name, IPaddr_t ip);
diff --git a/lib/driver.c b/lib/driver.c
index f433c3e..b600745 100644
--- a/lib/driver.c
+++ b/lib/driver.c
@@ -107,6 +107,7 @@ int register_device(struct device_d *new_device)
list_add_tail(&new_device->list, &device_list);
INIT_LIST_HEAD(&new_device->children);
INIT_LIST_HEAD(&new_device->cdevs);
+ INIT_LIST_HEAD(&new_device->parameters);
for_each_driver(drv) {
if (!match(drv, new_device))
@@ -313,16 +314,11 @@ static int do_devinfo(struct command *cmdtp, int argc, char *argv[])
if (dev->driver)
dev->driver->info(dev);
- param = dev->param;
+ printf("%s\n", list_empty(&dev->parameters) ?
+ "no parameters available" : "Parameters:");
- printf("%s\n", param ?
- "Parameters:" : "no parameters available");
-
- while (param) {
+ list_for_each_entry(param, &dev->parameters, list)
printf("%16s = %s\n", param->name, param->value);
- param = param->next;
- }
-
}
return 0;
diff --git a/lib/parameter.c b/lib/parameter.c
index 6b32207..a3d178f 100644
--- a/lib/parameter.c
+++ b/lib/parameter.c
@@ -33,17 +33,22 @@
struct param_d *get_param_by_name(struct device_d *dev, const char *name)
{
- struct param_d *param = dev->param;
+ struct param_d *p;
- while (param) {
- if (!strcmp(param->name, name))
- return param;
- param = param->next;
+ list_for_each_entry(p, &dev->parameters, list) {
+ if (!strcmp(p->name, name))
+ return p;
}
return NULL;
}
+/**
+ * dev_get_param - get the value of a parameter
+ * @param dev The device
+ * @param name The name of the parameter
+ * @return The value
+ */
const char *dev_get_param(struct device_d *dev, const char *name)
{
struct param_d *param = get_param_by_name(dev, name);
@@ -53,10 +58,7 @@ const char *dev_get_param(struct device_d *dev, const char *name)
return NULL;
}
- if (param->get)
- return param->get(dev, param);
-
- return param->value;
+ return param->get(dev, param);
}
#ifdef CONFIG_NET
@@ -80,6 +82,12 @@ int dev_set_param_ip(struct device_d *dev, char *name, IPaddr_t ip)
}
#endif
+/**
+ * dev_set_param - set a parameter of a device to a new value
+ * @param dev The device
+ * @param name The name of the parameter
+ * @param value The new value of the parameter
+ */
int dev_set_param(struct device_d *dev, const char *name, const char *val)
{
struct param_d *param;
@@ -101,35 +109,122 @@ int dev_set_param(struct device_d *dev, const char *name, const char *val)
return -EACCES;
}
- if (param->set) {
- errno = param->set(dev, param, val);
- return errno;
- }
-
- if (param->value)
- free(param->value);
+ errno = param->set(dev, param, val);
+ return errno;
+}
- param->value = strdup(val);
+/**
+ * dev_param_set_generic - generic setter function for a parameter
+ * @param dev The device
+ * @param p the parameter
+ * @param val The new value
+ *
+ * If used the value of a parameter is a string allocated with
+ * malloc and freed with free. If val is NULL the value is freed. This is
+ * used during deregistration of the parameter to free the alloctated
+ * memory.
+ */
+int dev_param_set_generic(struct device_d *dev, struct param_d *p,
+ const char *val)
+{
+ if (p->value)
+ free(p->value);
+ if (!val)
+ return 0;
+ p->value = strdup(val);
return 0;
}
-int dev_add_param(struct device_d *dev, struct param_d *newparam)
+static char *param_get_generic(struct device_d *dev, struct param_d *p)
+{
+ return p->value;
+}
+
+static struct param_d *__dev_add_param(struct device_d *dev, char *name,
+ int (*set)(struct device_d *dev, struct param_d *p, const char *val),
+ char *(*get)(struct device_d *dev, struct param_d *p),
+ unsigned long flags)
{
- struct param_d *param = dev->param;
+ struct param_d *param;
- newparam->next = NULL;
+ param = xzalloc(sizeof(*param));
- if (param) {
- while (param->next)
- param = param->next;
- param->next = newparam;
- } else {
- dev->param = newparam;
- }
+ if (set)
+ param->set = set;
+ else
+ param->set = dev_param_set_generic;
+ if (get)
+ param->get = get;
+ else
+ param->get = param_get_generic;
+
+ param->name = strdup(name);
+ param->flags = flags;
+ list_add_tail(¶m->list, &dev->parameters);
+
+ return param;
+}
+
+/**
+ * dev_add_param - add a parameter to a device
+ * @param dev The device
+ * @param name The name of the parameter
+ * @param set setter function for the parameter
+ * @param get getter function for the parameter
+ * @param flags
+ *
+ * This function adds a new parameter to a device. The get/set functions can
+ * be zero in which case the generic functions are used. The generic functions
+ * expect the parameter value to be a string which can be freed with free(). Do
+ * not use static arrays when using the generic functions.
+ */
+int dev_add_param(struct device_d *dev, char *name,
+ int (*set)(struct device_d *dev, struct param_d *p, const char *val),
+ char *(*get)(struct device_d *dev, struct param_d *param),
+ unsigned long flags)
+{
+ struct param_d *param;
+
+ param = __dev_add_param(dev, name, set, get, flags);
+
+ return param ? 0 : -EINVAL;
+}
+
+/**
+ * dev_add_param_fixed - add a readonly parameter to a device
+ * @param dev The device
+ * @param name The name of the parameter
+ * @param value The value of the parameter
+ */
+int dev_add_param_fixed(struct device_d *dev, char *name, char *value)
+{
+ struct param_d *param;
+
+ param = __dev_add_param(dev, name, NULL, NULL, PARAM_FLAG_RO);
+ if (!param)
+ return -EINVAL;
+
+ param->value = strdup(value);
return 0;
}
+/**
+ * dev_remove_parameters - remove all parameters from a device and free their
+ * memory
+ * @param dev The device
+ */
+void dev_remove_parameters(struct device_d *dev)
+{
+ struct param_d *p, *n;
+
+ list_for_each_entry_safe(p, n, &dev->parameters, list) {
+ p->set(dev, p, NULL);
+ list_del(&p->list);
+ free(p);
+ }
+}
+
/** @page dev_params Device parameters
@section params_devices Devices can have several parameters.
@@ -145,50 +240,6 @@ IP address of the first ethernet device is a matter of typing
devices currently present. If called with a device id as parameter it shows the
parameters available for a device.
-@section params_programming Device parameters programming API
-
-@code
-struct param_d {
- char* (*get)(struct device_d *, struct param_d *param);
- int (*set)(struct device_d *, struct param_d *param, const char *val);
- ulong flags;
- char *name;
- struct param_d *next;
- char *value;
-};
-@endcode
-
-@code
-int dev_add_param(struct device_d *dev, struct param_d *newparam);
-@endcode
-
-This function adds a new parameter to a device. At least the name field in
-the new parameter struct has to be initialized. The 'get' and 'set' fields
-can be set to NULL in which case the framework handles them. It is also
-allowed to implement only one of the get/set functions. Care must be taken
-with the initial value of the parameter. If the framework handles the set
-function it will try to free the value of the parameter. If this is a
-static array bad things will happen. A parameter can have the flag
-PARAM_FLAG_RO which means that the parameter is readonly. It is perfectly ok
-then to point the value to a static array.
-
-@code
-const char *dev_get_param(struct device_d *dev, const char *name);
-@endcode
-
-This function returns a pointer to the value of the parameter specified
-with dev and name.
-If the framework handles the get/set functions the parameter value strings
-are alloceted with malloc and freed with free when another value is set for
-this parameter. Drivers implementing set/get themselves are allowed to
-return values in static arrays. This means that the pointers returned from
-dev_get_param() are only valid until the next call to dev_get_param. If this
-is not long enough strdup() or similar must be used.
-
-@code
-int dev_set_param(struct device_d *dev, const char *name, const char *val);
-@endcode
-
-Set the value of a parameter.
+See the individual functions for parameter programming.
*/
diff --git a/net/eth.c b/net/eth.c
index fc16233..4d58191 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -102,11 +102,13 @@ static int eth_set_ethaddr(struct device_d *dev, struct param_d *param, const ch
struct eth_device *edev = dev->type_data;
char ethaddr[sizeof("xx:xx:xx:xx:xx:xx")];
+ if (!val)
+ return dev_param_set_generic(dev, param, NULL);
+
if (string_to_ethaddr(val, ethaddr) < 0)
return -EINVAL;
- free(param->value);
- param->value = strdup(val);
+ dev_param_set_generic(dev, param, val);
edev->set_ethaddr(edev, ethaddr);
@@ -121,11 +123,13 @@ static int eth_set_ipaddr(struct device_d *dev, struct param_d *param, const cha
struct eth_device *edev = dev->type_data;
IPaddr_t ip;
+ if (!val)
+ return dev_param_set_generic(dev, param, NULL);
+
if (string_to_ip(val, &ip))
return -EINVAL;
- free(param->value);
- param->value = strdup(val);
+ dev_param_set_generic(dev, param, val);
if (edev == eth_current)
net_update_env();
@@ -148,21 +152,11 @@ int eth_register(struct eth_device *edev)
register_device(&edev->dev);
dev->type_data = edev;
- edev->param_ip.name = "ipaddr";
- edev->param_ip.set = ð_set_ipaddr;
- edev->param_ethaddr.name = "ethaddr";
- edev->param_ethaddr.set = ð_set_ethaddr;
- edev->param_gateway.name = "gateway";
- edev->param_gateway.set = ð_set_ipaddr;
- edev->param_netmask.name = "netmask";
- edev->param_netmask.set = ð_set_ipaddr;
- edev->param_serverip.name = "serverip";
- edev->param_serverip.set = ð_set_ipaddr;
- dev_add_param(dev, &edev->param_ip);
- dev_add_param(dev, &edev->param_ethaddr);
- dev_add_param(dev, &edev->param_gateway);
- dev_add_param(dev, &edev->param_netmask);
- dev_add_param(dev, &edev->param_serverip);
+ dev_add_param(dev, "ipaddr", eth_set_ipaddr, NULL, 0);
+ dev_add_param(dev, "ethaddr", eth_set_ethaddr, NULL, 0);
+ dev_add_param(dev, "gateway", eth_set_ipaddr, NULL, 0);
+ dev_add_param(dev, "netmask", eth_set_ipaddr, NULL, 0);
+ dev_add_param(dev, "serverip", eth_set_ipaddr, NULL, 0);
edev->init(edev);
@@ -182,21 +176,7 @@ int eth_register(struct eth_device *edev)
void eth_unregister(struct eth_device *edev)
{
- if (edev->param_ip.value)
- free(edev->param_ip.value);
- if (edev->param_ethaddr.value)
- free(edev->param_ethaddr.value);
- if (edev->param_gateway.value)
- free(edev->param_gateway.value);
- if (edev->param_netmask.value)
- free(edev->param_netmask.value);
- if (edev->param_serverip.value)
- free(edev->param_serverip.value);
-
- if (eth_current == edev) {
- eth_current->halt(eth_current);
- eth_current = NULL;
- }
+ dev_remove_parameters(&edev->dev);
list_del(&edev->list);
}
--
1.7.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 12/13] errno: add strings for network related error messages
2010-06-04 9:54 reworking the network stack Sascha Hauer
` (10 preceding siblings ...)
2010-06-04 9:55 ` [PATCH 11/13] rework device parameters Sascha Hauer
@ 2010-06-04 9:55 ` Sascha Hauer
2010-06-04 9:55 ` [PATCH 13/13] add netconsole support Sascha Hauer
12 siblings, 0 replies; 18+ messages in thread
From: Sascha Hauer @ 2010-06-04 9:55 UTC (permalink / raw)
To: barebox
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
common/misc.c | 7 ++++---
1 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/common/misc.c b/common/misc.c
index b3292d3..7edf536 100644
--- a/common/misc.c
+++ b/common/misc.c
@@ -56,6 +56,10 @@ const char *strerror(int errnum)
case ENAMETOOLONG : str = "File name too long"; break;
case ENOSYS : str = "Function not implemented"; break;
case ENOTEMPTY : str = "Directory not empty"; break;
+ case EHOSTUNREACH : str = "No route to host"; break;
+ case EINTR : str = "Interrupted system call"; break;
+ case ENETUNREACH : str = "Network is unreachable"; break;
+ case ENETDOWN : str = "Network is down"; break;
#if 0 /* These are probably not needed */
case ENOTBLK : str = "Block device required"; break;
case EFBIG : str = "File too large"; break;
@@ -79,8 +83,6 @@ const char *strerror(int errnum)
case EAFNOSUPPORT : str = "Address family not supported by protocol"; break;
case EADDRINUSE : str = "Address already in use"; break;
case EADDRNOTAVAIL : str = "Cannot assign requested address"; break;
- case ENETDOWN : str = "Network is down"; break;
- case ENETUNREACH : str = "Network is unreachable"; break;
case ENETRESET : str = "Network dropped connection because of reset"; break;
case ECONNABORTED : str = "Software caused connection abort"; break;
case ECONNRESET : str = "Connection reset by peer"; break;
@@ -88,7 +90,6 @@ const char *strerror(int errnum)
case ETIMEDOUT : str = "Connection timed out"; break;
case ECONNREFUSED : str = "Connection refused"; break;
case EHOSTDOWN : str = "Host is down"; break;
- case EHOSTUNREACH : str = "No route to host"; break;
case EALREADY : str = "Operation already in progress"; break;
case EINPROGRESS : str = "Operation now in progress"; break;
case ESTALE : str = "Stale NFS file handle"; break;
--
1.7.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 13/13] add netconsole support
2010-06-04 9:54 reworking the network stack Sascha Hauer
` (11 preceding siblings ...)
2010-06-04 9:55 ` [PATCH 12/13] errno: add strings for network related error messages Sascha Hauer
@ 2010-06-04 9:55 ` Sascha Hauer
2010-06-24 15:21 ` Eric Bénard
12 siblings, 1 reply; 18+ messages in thread
From: Sascha Hauer @ 2010-06-04 9:55 UTC (permalink / raw)
To: barebox
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
Documentation/users_manual.dox | 1 +
Doxyfile | 3 +-
net/Kconfig | 7 ++
net/Makefile | 1 +
net/netconsole.c | 228 ++++++++++++++++++++++++++++++++++++++++
5 files changed, 239 insertions(+), 1 deletions(-)
create mode 100644 net/netconsole.c
diff --git a/Documentation/users_manual.dox b/Documentation/users_manual.dox
index 5467bee..cd2b99c 100644
--- a/Documentation/users_manual.dox
+++ b/Documentation/users_manual.dox
@@ -11,5 +11,6 @@ work easier.
@li @subpage command_reference
@li @subpage partitions
@li @subpage x86_bootloader
+@li @subpage net_netconsole
*/
diff --git a/Doxyfile b/Doxyfile
index 94dd6ae..40bcb2f 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -485,7 +485,8 @@ INPUT = Documentation \
common \
board \
lib \
- scripts/setupmbr
+ scripts/setupmbr \
+ net
# This tag can be used to specify the character encoding of the source files that
# doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default
diff --git a/net/Kconfig b/net/Kconfig
index a110bec..faf2c28 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -18,4 +18,11 @@ config NET_PING
config NET_TFTP
bool
prompt "tftp support"
+
+config NET_NETCONSOLE
+ bool
+ prompt "network console support"
+ help
+ This option adds support for a simple udp based network console.
+
endif
diff --git a/net/Makefile b/net/Makefile
index bba6f0e..e42a484 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -4,3 +4,4 @@ obj-$(CONFIG_NET) += net.o
obj-$(CONFIG_NET_NFS) += nfs.o
obj-$(CONFIG_NET_TFTP) += tftp.o
obj-$(CONFIG_NET_PING) += ping.o
+obj-$(CONFIG_NET_NETCONSOLE) += netconsole.o
diff --git a/net/netconsole.c b/net/netconsole.c
new file mode 100644
index 0000000..07e6a6c
--- /dev/null
+++ b/net/netconsole.c
@@ -0,0 +1,228 @@
+/*
+ * netconsole.c - network console support
+ *
+ * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <command.h>
+#include <fs.h>
+#include <linux/stat.h>
+#include <errno.h>
+#include <malloc.h>
+#include <getopt.h>
+#include <stringlist.h>
+#include <net.h>
+#include <kfifo.h>
+#include <init.h>
+#include <linux/err.h>
+
+/**
+ * @file
+ * @brief Network console support
+ */
+
+struct nc_priv {
+ struct console_device cdev;
+ struct kfifo *fifo;
+ int busy;
+ struct net_connection *con;
+
+ uint16_t port;
+ IPaddr_t ip;
+};
+
+static struct nc_priv *g_priv;
+
+static void nc_handler(char *pkt, unsigned len)
+{
+ struct nc_priv *priv = g_priv;
+ unsigned char *packet = net_eth_to_udp_payload(pkt);
+
+ kfifo_put(priv->fifo, packet, net_eth_to_udplen(pkt));
+}
+
+static int nc_init(void)
+{
+ struct nc_priv *priv = g_priv;
+
+ if (priv->con)
+ net_unregister(priv->con);
+
+ priv->con = net_udp_new(priv->ip, priv->port, nc_handler);
+ if (IS_ERR(priv->con)) {
+ int ret = PTR_ERR(priv->con);
+ priv->con = NULL;
+ return ret;
+ }
+
+ net_udp_bind(priv->con, priv->port);
+ priv->cdev.f_caps = CONSOLE_STDIN | CONSOLE_STDOUT | CONSOLE_STDERR;
+ return 0;
+}
+
+static int nc_getc(struct console_device *cdev)
+{
+ struct nc_priv *priv = container_of(cdev,
+ struct nc_priv, cdev);
+ unsigned char c;
+
+ while (!kfifo_len(priv->fifo))
+ net_poll();
+
+ kfifo_getc(priv->fifo, &c);
+
+ return c;
+}
+
+static int nc_tstc(struct console_device *cdev)
+{
+ struct nc_priv *priv = container_of(cdev,
+ struct nc_priv, cdev);
+
+ if (priv->busy)
+ return kfifo_len(priv->fifo) ? 1 : 0;
+
+ net_poll();
+
+ return kfifo_len(priv->fifo) ? 1 : 0;
+}
+
+static void nc_putc(struct console_device *cdev, char c)
+{
+ struct nc_priv *priv = container_of(cdev,
+ struct nc_priv, cdev);
+ unsigned char *packet;
+
+ if (!priv->con)
+ return;
+
+ if (priv->busy)
+ return;
+
+ packet = net_udp_get_payload(priv->con);
+ *packet = c;
+
+ priv->busy = 1;
+ net_udp_send(priv->con, 1);
+ priv->busy = 0;
+}
+
+static int nc_setbaudrate(struct console_device *cdev, int baudrate)
+{
+ return 0;
+}
+
+static int nc_port_set(struct device_d *dev, struct param_d *param,
+ const char *val)
+{
+ struct nc_priv *priv = g_priv;
+ char portstr[16];
+ int port;
+
+ if (!val)
+ dev_param_set_generic(dev, param, NULL);
+
+ port = simple_strtoul(val, NULL, 10);
+ if (port > 65535)
+ return -EINVAL;
+
+ priv->port = port;
+ nc_init();
+
+ sprintf(portstr, "%d", port);
+ dev_param_set_generic(dev, param, portstr);
+
+ return 0;
+}
+
+static int nc_remoteip_set(struct device_d *dev, struct param_d *param,
+ const char *val)
+{
+ struct nc_priv *priv = g_priv;
+ IPaddr_t ip;
+ int ret;
+
+ if (!val)
+ dev_param_set_generic(dev, param, NULL);
+
+ if (string_to_ip(val, &ip))
+ return -EINVAL;
+
+ priv->ip = ip;
+ ret = nc_init();
+ if (ret)
+ return ret;
+
+ dev_param_set_generic(dev, param, val);
+
+ return 0;
+}
+
+static int netconsole_init(void)
+{
+ struct nc_priv *priv;
+ struct console_device *cdev;
+
+ priv = xzalloc(sizeof(*priv));
+ cdev = &priv->cdev;
+ cdev->tstc = nc_tstc;
+ cdev->putc = nc_putc;
+ cdev->getc = nc_getc;
+ cdev->setbrg = nc_setbaudrate;
+
+ g_priv = priv;
+
+ priv->fifo = kfifo_alloc(1024);
+
+ console_register(cdev);
+
+ dev_add_param(&cdev->class_dev, "ip", nc_remoteip_set, NULL, 0);
+ dev_add_param(&cdev->class_dev, "port", nc_port_set, NULL, 0);
+ dev_set_param(&cdev->class_dev, "port", "6666");
+
+ printf("registered netconsole as %s%d\n", cdev->class_dev.name, cdev->class_dev.id);
+
+ return 0;
+}
+
+device_initcall(netconsole_init);
+
+/** @page net_netconsole Network console
+
+@section net_netconsole Using an UDP based network console
+
+If enabled barebox supports a console via udp networking. There is only
+one network console supported registered during init time. It is deactivated
+by default because it opens great security holes, so use with care.
+
+To use the network console you have to configure the remote ip and the local
+and remote ports. Assuming the network console is registered as cs1, it can be
+configured with:
+
+@code
+cs1.ip=<remotehost>
+cs1.port=<port>
+cs1.active=ioe
+@endcode
+
+On the remote host call scripts/netconsole with bareboxes ip and port as
+parameters. port is initialized to 6666 by default.
+
+*/
--
1.7.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 13/13] add netconsole support
2010-06-04 9:55 ` [PATCH 13/13] add netconsole support Sascha Hauer
@ 2010-06-24 15:21 ` Eric Bénard
2010-06-24 15:27 ` Eric Bénard
2010-06-24 15:37 ` Sascha Hauer
0 siblings, 2 replies; 18+ messages in thread
From: Eric Bénard @ 2010-06-24 15:21 UTC (permalink / raw)
To: Sascha Hauer; +Cc: barebox
Hi Sascha,
Le 04/06/2010 11:55, Sascha Hauer a écrit :
> +
> +On the remote host call scripts/netconsole with bareboxes ip and port as
> +parameters. port is initialized to 6666 by default.
> +
it seems scripts/netconsol is missing from the tree and the netconsole
patche.
Eric
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 13/13] add netconsole support
2010-06-24 15:21 ` Eric Bénard
@ 2010-06-24 15:27 ` Eric Bénard
2010-06-24 15:37 ` Sascha Hauer
1 sibling, 0 replies; 18+ messages in thread
From: Eric Bénard @ 2010-06-24 15:27 UTC (permalink / raw)
To: Sascha Hauer; +Cc: barebox
Le 24/06/2010 17:21, Eric Bénard a écrit :
>> +On the remote host call scripts/netconsole with bareboxes ip and port as
>> +parameters. port is initialized to 6666 by default.
>> +
> it seems scripts/netconsol is missing from the tree and the netconsole
> patche.
>
OK this seems to work :
netcat -p 6666 -l -u IP_OF_BAREBOX
Eric
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 13/13] add netconsole support
2010-06-24 15:21 ` Eric Bénard
2010-06-24 15:27 ` Eric Bénard
@ 2010-06-24 15:37 ` Sascha Hauer
2010-06-25 6:58 ` Eric Bénard
1 sibling, 1 reply; 18+ messages in thread
From: Sascha Hauer @ 2010-06-24 15:37 UTC (permalink / raw)
To: Eric Bénard; +Cc: barebox
On Thu, Jun 24, 2010 at 05:21:14PM +0200, Eric Bénard wrote:
> Hi Sascha,
>
> Le 04/06/2010 11:55, Sascha Hauer a écrit :
>> +
>> +On the remote host call scripts/netconsole with bareboxes ip and port as
>> +parameters. port is initialized to 6666 by default.
>> +
> it seems scripts/netconsol is missing from the tree and the netconsole
> patche.
Oh, I had it in my tree and forgot to commit. Did now.
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 13/13] add netconsole support
2010-06-24 15:37 ` Sascha Hauer
@ 2010-06-25 6:58 ` Eric Bénard
0 siblings, 0 replies; 18+ messages in thread
From: Eric Bénard @ 2010-06-25 6:58 UTC (permalink / raw)
To: Sascha Hauer; +Cc: barebox
Hi Sascha,
Le 24/06/2010 17:37, Sascha Hauer a écrit :
> On Thu, Jun 24, 2010 at 05:21:14PM +0200, Eric Bénard wrote:
>> it seems scripts/netconsol is missing from the tree and the netconsole
>> patche.
>
> Oh, I had it in my tree and forgot to commit. Did now.
>
thanks works fine, this netconsole is really a nice feature.
Eric
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2010-06-25 6:58 UTC | newest]
Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-06-04 9:54 reworking the network stack Sascha Hauer
2010-06-04 9:54 ` [PATCH 01/13] net: remove need for eth_halt/eth_open Sascha Hauer
2010-06-04 9:54 ` [PATCH 02/13] net: Implement a new network stack Sascha Hauer
2010-06-04 9:54 ` [PATCH 03/13] remove unused sntp.h Sascha Hauer
2010-06-04 9:55 ` [PATCH 04/13] implement dhcp using new network stack Sascha Hauer
2010-06-04 9:55 ` [PATCH 05/13] implement tftp " Sascha Hauer
2010-06-04 9:55 ` [PATCH 06/13] implement ping " Sascha Hauer
2010-06-04 9:55 ` [PATCH 07/13] implement nfs " Sascha Hauer
2010-06-04 9:55 ` [PATCH 08/13] net: consider rarp support as outdated. Remove it Sascha Hauer
2010-06-04 9:55 ` [PATCH 09/13] network drivers: call net_receive directly instead of NetReceive Sascha Hauer
2010-06-04 9:55 ` [PATCH 10/13] net: remove old network stack Sascha Hauer
2010-06-04 9:55 ` [PATCH 11/13] rework device parameters Sascha Hauer
2010-06-04 9:55 ` [PATCH 12/13] errno: add strings for network related error messages Sascha Hauer
2010-06-04 9:55 ` [PATCH 13/13] add netconsole support Sascha Hauer
2010-06-24 15:21 ` Eric Bénard
2010-06-24 15:27 ` Eric Bénard
2010-06-24 15:37 ` Sascha Hauer
2010-06-25 6:58 ` Eric Bénard
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox