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.
This commit is contained in:
parent
dca25a1b39
commit
8171eb0b3d
3 changed files with 76 additions and 7 deletions
|
@ -16,6 +16,8 @@
|
|||
#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>
|
||||
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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. */
|
||||
|
|
Loading…
Reference in a new issue