From: Tomas Hruby Date: Thu, 7 Apr 2011 07:44:17 +0000 (+0000) Subject: LWIP - dhcpd --lwip X-Git-Tag: v3.2.0~592 X-Git-Url: http://zhaoyanbai.com/repos/Bv9ARM.ch07.html?a=commitdiff_plain;h=8171eb0b3d676c25c5222b596fc34c52eb2440a3;p=minix.git LWIP - dhcpd --lwip A sort of quick hack for dhcpd to work as a client with lwip server. - The functionality is not changed unless --lwip switch is supplied. dhcpd does not use broadcast udp sockets but some sort of raw sockets and changes their behavior during their life by ioctls. - I thought there is no need to polute lwip just to make dhcp client work. Instead I decided to twist the client a little bit. - It is so far the only big collision I found between inet and lwip. --- diff --git a/commands/dhcpd/devices.c b/commands/dhcpd/devices.c index 9a39177f2..7b095372d 100644 --- a/commands/dhcpd/devices.c +++ b/commands/dhcpd/devices.c @@ -16,6 +16,8 @@ #include #include #include +#include +#include #include #include #include @@ -166,7 +168,10 @@ int opendev(network_t *np, fdtype_t fdtype, int compete) /* 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) { @@ -176,6 +181,38 @@ int opendev(network_t *np, fdtype_t fdtype, int compete) 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 @@ -218,6 +255,26 @@ int opendev(network_t *np, fdtype_t fdtype, int compete) 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; diff --git a/commands/dhcpd/dhcpd.c b/commands/dhcpd/dhcpd.c index 8b82fac1a..50c1a62af 100644 --- a/commands/dhcpd/dhcpd.c +++ b/commands/dhcpd/dhcpd.c @@ -45,6 +45,8 @@ static int aflag, rflag; /* True if adding or deleting pool addresses. */ #define N_NETS 32 static unsigned n_nets; /* Actual number of networks. */ +int lwip; + void report(const char *label) { static FILE *logfp; @@ -685,6 +687,11 @@ main: 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': @@ -776,7 +783,9 @@ main: 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", @@ -956,8 +965,8 @@ main: 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", @@ -1007,8 +1016,9 @@ main: 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); @@ -1026,7 +1036,7 @@ main: 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) diff --git a/commands/dhcpd/dhcpd.h b/commands/dhcpd/dhcpd.h index ba7a1329b..93bf5a899 100644 --- a/commands/dhcpd/dhcpd.h +++ b/commands/dhcpd/dhcpd.h @@ -19,6 +19,8 @@ #define EXTERN extern #endif +extern int lwip; + EXTERN char *program; /* This program's name. */ extern char *configfile; /* Configuration file. */ extern char *poolfile; /* Dynamic address pool. */