]> Zhao Yanbai Git Server - minix.git/commitdiff
LWIP - dhcpd --lwip
authorTomas Hruby <tom@minix3.org>
Thu, 7 Apr 2011 07:44:17 +0000 (07:44 +0000)
committerTomas Hruby <tom@minix3.org>
Thu, 7 Apr 2011 07:44:17 +0000 (07:44 +0000)
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.

commands/dhcpd/devices.c
commands/dhcpd/dhcpd.c
commands/dhcpd/dhcpd.h

index 9a39177f2e7f298cc899d876fe999e5133a42267..7b095372db657f42399e4b81eca3f6493fabf43f 100644 (file)
@@ -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, &ethstat) < 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;
index 8b82fac1a33a563b15b3a68ac791693cfef86e6a..50c1a62afb4f5877c1567a9e253d525cef878b51 100644 (file)
@@ -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)
index ba7a1329b510962b7a6bb57675e31b2d1be0638c..93bf5a89987c9a6f1ba85aa56d6503f178f2bfc6 100644 (file)
@@ -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. */