#include <sys/asynchio.h>
#include <net/hton.h>
#include <net/gen/in.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
#include <net/gen/ether.h>
#include <net/gen/eth_hdr.h>
#include <net/gen/eth_io.h>
/* Open the proper device in the proper mode. */
fdp= fdold;
fdp->n= np->n;
- sprintf(fdp->device, "/dev/%s%d", devbytype[fdtype], np->n);
+ if (lwip && (fdtype == FT_ETHERNET || fdtype == FT_ICMP))
+ sprintf(fdp->device, "/dev/ip");
+ else
+ sprintf(fdp->device, "/dev/%s%d", devbytype[fdtype], np->n);
np->fdp= fdp;
if ((fdp->fd= open(fdp->device, O_RDWR)) < 0) {
switch (fdtype) {
case FT_ETHERNET:
+ if (lwip) {
+ nwio_ipopt_t ipopt;
+ int result;
+ char ethdev[64];
+ int efd;
+
+ sprintf(ethdev, "/dev/eth%d", np->n);
+
+ if ((efd = open(fdp->device, O_RDWR)) < 0) {
+ if (errno == ENOENT || errno == ENODEV ||
+ errno == ENXIO)
+ return 0;
+ fatal(ethdev);
+ }
+
+ if (ioctl(efd, NWIOGETHSTAT, ðstat) < 0) {
+ /* Not an Ethernet. */
+ close(efd);
+ return 0;
+ }
+ close(efd);
+
+ np->eth= ethstat.nwes_addr;
+
+ ipopt.nwio_flags= NWIO_COPY | NWIO_PROTOSPEC;
+ ipopt.nwio_proto= 17; /* UDP */
+ result= ioctl (fdp->fd, NWIOSIPOPT, &ipopt);
+ if (result<0)
+ perror("ioctl (NWIOSIPOPT)"), exit(1);
+
+ break;
+ }
/* Cannot use NWIOGETHSTAT in non-blocking mode due to a race between
* the reply from the ethernet driver and the cancel message from VFS
* for reaching inet. Hence, a signal is used to interrupt NWIOGETHSTAT
break;
case FT_BOOTPC:
+ if (lwip) {
+ struct sockaddr_in si_me;
+
+ close(fdp->fd);
+ fdp->fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (fdp->fd < 0)
+ return 0;
+ memset((char *) &si_me, 0, sizeof(si_me));
+ si_me.sin_family = AF_INET;
+ si_me.sin_addr.s_addr = htonl(INADDR_ANY);
+ si_me.sin_port = htons(port_client);
+ if (bind(fdp->fd, (struct sockaddr *) &si_me,
+ sizeof(si_me)) == -1) {
+ close(fdp->fd);
+ printf("DHCP : cannot bind client socket to port %d\n",
+ port_client);
+ return 0;
+ }
+ break;
+ }
udpopt.nwuo_flags= NWUO_COPY | NWUO_EN_LOC | NWUO_EN_BROAD
| NWUO_RP_ANY | NWUO_RA_ANY | NWUO_RWDATALL
| NWUO_DI_IPOPT | NWUO_LP_SET;
#define N_NETS 32
static unsigned n_nets; /* Actual number of networks. */
+int lwip;
+
void report(const char *label)
{
static FILE *logfp;
char *opt= argv[i++]+1;
if (opt[0] == '-' && opt[1] == 0) break; /* -- */
+
+ if (strcmp(opt, "-lwip") == 0) {
+ lwip = 1;
+ continue;
+ }
while (*opt != 0) switch (*opt++) {
case 'f':
np->n= i;
/* Ethernet? */
- if (opendev(np, FT_ETHERNET, 1)) {
+ if (lwip) {
+ np->type = NT_ETHERNET;
+ } else if (opendev(np, FT_ETHERNET, 1)) {
np->type= B(&np->eth)[0] != 'Z' ? NT_ETHERNET : NT_SINK;
if (debug >= 1) {
printf("%s: Ethernet address is %s%s\n",
if (!(np->flags & NF_BOUND)) {
/* Rebind over Ethernet. */
udp2ether(bp, np);
- if (sendpacket(np, bp->eth,
- sizeof(eth_hdr_t) + sizeof(ip_hdr_t)
+ if (sendpacket(np, (lwip ? bp->ip : bp->eth),
+ (lwip ? 0 : sizeof(eth_hdr_t)) + sizeof(ip_hdr_t)
+ sizeof(udp_hdr_t) + sizeof(dhcp_t))) {
if (debug >= 1) {
printf("%s: Broadcast DHCP %s\n",
if (!(np->flags & NF_BOUND)) {
if (!opendev(np, FT_ETHERNET, 0)) continue;
get_buf(&np->fdp->bp);
- r= asyn_read(&asyn, np->fdp->fd, np->fdp->bp->eth,
- BUF_ETH_SIZE);
+ r= asyn_read(&asyn, np->fdp->fd,
+ lwip ? np->fdp->bp->ip : np->fdp->bp->eth,
+ lwip ? BUF_IP_SIZE : BUF_ETH_SIZE);
} else {
if (!opendev(np, FT_BOOTPC, 0)) continue;
get_buf(&np->fdp->bp);
if (i < n_nets) {
give_buf(&bp, &np->fdp->bp);
if (((!(np->flags & NF_BOUND)
- && r >= (sizeof(eth_hdr_t) + sizeof(ip_hdr_t)
+ && r >= (lwip ? 0 : (sizeof(eth_hdr_t)) + sizeof(ip_hdr_t)
+ sizeof(udp_hdr_t) + offsetof(dhcp_t, options))
&& ether2udp(bp)
&& bp->udpio->uih_dst_port == port_client)