www.usr.com/support/gpl/USR9107_release.1.4.tar.gz
[bcm963xx.git] / userapps / opensource / busybox / networking / tftpd.c
index 8c939ec..6971a28 100755 (executable)
@@ -32,6 +32,7 @@
 #include <sys/time.h>
 #include <sys/stat.h>
 #include <netdb.h>
+#include <syslog.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <arpa/tftp.h>
 #include <sys/ioctl.h>
 #include <signal.h>
 #include <errno.h>
+
+// Keven Kuo
+#include <config.h>
+#ifdef HAVE_ASM_SOCKET_H
+#include <asm/socket.h>
+#endif
+#ifdef HAVE_WAIT_H
+# include <wait.h>
+#else
+# ifdef HAVE_SYS_WAIT_H
+#  include <sys/wait.h>
+# endif
+#endif
+
 #include "busybox.h"
 
+// Keven Kuo
+#define DAEMONIZE
+
 #ifndef OACK
 #define OACK 6
 #endif
@@ -683,29 +701,60 @@ tftpd_daemon (char *directory, char *address, int port)
   struct msghdr msg = { (void*)&from, sizeof from, &iov, 1, (void*)ctrl, MAXCTRLSIZE, 0};
   struct in_pktinfo *info = NULL;
 
+#ifdef DAEMONIZE
+    daemon(0,1);
+#endif
+
   if ((fd = socket (PF_INET, SOCK_DGRAM, 0)) < 0)
     perror_msg_and_die ("socket");
+
+  // Keven Kuo -- no need for inetd
+#ifdef DAEMONIZE
+  // set option for getting the to ip address.
+  setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &i, sizeof(i)); 
+#else
+  #ifdef SO_REUSEADDR
+  setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *) &i, sizeof(i));
+  #endif
+  #ifdef SO_REUSEPORT
+  setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (void *) &i, sizeof(i));
+  #endif
+#endif
   memset (&bindaddr, 0, sizeof (bindaddr));
   bindaddr.sin_family = AF_INET;
-  bindaddr.sin_addr.s_addr = INADDR_ANY;
   bindaddr.sin_port = htons (port);
   if (address != NULL)
-    {
+  {
       struct hostent *hostent;
       hostent = xgethostbyname (address);
       if (!hostent || hostent->h_addrtype != AF_INET)
        perror_msg_and_die ("cannot resolve local bind address");
       memcpy (&bindaddr.sin_addr, hostent->h_addr, hostent->h_length);
-    }
-  // set option for getting the to ip address.
-  setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &i, sizeof(i));
+  }
 
   if (bind (fd, (struct sockaddr *) &bindaddr, sizeof (bindaddr)) < 0)
     perror_msg_and_die ("daemon bind failed");
   /* This means we don't want to wait() for children */
   signal (SIGCHLD, SIG_IGN);
-  while (1)
+
+  // get pid for web access function to start/stop tftpd.
+#ifdef DAEMONIZE
+  {
+    FILE *pid_fp;
+    if (!(pid_fp = fopen("/var/run/tftpd_pid", "w"))) 
     {
+        printf("Error open /var/run/tftpd_pid");
+        exit(0);
+    }
+    fprintf(pid_fp, "%d\n", getpid());
+    fclose(pid_fp);
+  }
+#endif
+
+#ifdef DAEMONIZE
+  while (1)
+#endif
+  {
       fd_set readset;
       memset(buf,0,TFTP_BLOCKSIZE_DEFAULT + 4);
       memset (&myaddr, 0, sizeof (myaddr));
@@ -714,46 +763,66 @@ tftpd_daemon (char *directory, char *address, int port)
       /* Never time out, we're in standalone mode */
       rv = select (fd + 1, &readset, NULL, NULL, NULL);
       if (rv == -1 && errno == EINTR)
+        // Keven Kuo
+#ifdef DAEMONIZE
        continue;               /* Signal caught, reloop */
+#else
+        exit (0);
+#endif
       if (rv == -1)
        perror_msg_and_die ("select loop");
       if (rv == 0)
-       {
+      {
          bb_error_msg ("We shouldn't be timeing out!");
          exit (0);             /* Timeout, return to inetd */
-       }
+      }
 
       n = recvmsg (fd, &msg, MSG_WAITALL);
       if (n <= 0)
       {
-          printf("*** error recvmsg n=%d\n", n);
-          break;
+          if (n == 0)  /* Keven -- Received message with zero length, reloop */
+            // Keven Kuo
+#ifdef DAEMONIZE
+            continue;
+#else
+            exit (0);
+#endif
+          else {       
+            printf("*** error recvmsg n=%d\n", n);
+            // Keven Kuo
+#ifdef DAEMONIZE
+            break;
+#else
+            exit (0);
+#endif
+          }
       }
-//printf("incoming_ip=%s, n=%d\n", inet_ntoa(from.sin_addr), n);
-       for(cmsg=CMSG_FIRSTHDR(&msg); cmsg != NULL;cmsg =CMSG_NXTHDR(&msg,cmsg)) {
-               if (cmsg->cmsg_type == IP_PKTINFO){
-                   info = (struct in_pktinfo *)CMSG_DATA(cmsg);
-//            printf("sepc_dst=%s, ipi_addr=%s\n", inet_ntoa(info->ipi_spec_dst),inet_ntoa(info->ipi_addr));
+      for(cmsg=CMSG_FIRSTHDR(&msg); cmsg != NULL;cmsg =CMSG_NXTHDR(&msg,cmsg)) {
+          if (cmsg->cmsg_type == IP_PKTINFO){
+            info = (struct in_pktinfo *)CMSG_DATA(cmsg);
             break;
-               }
-    }
-    free(ctrl);
-  /* Process the request */
-  myaddr.sin_family = AF_INET;
-  myaddr.sin_port = htons (0); /* we want a new local port */
-  myaddr.sin_addr = getLanIp();
-
-  if (myaddr.sin_addr.s_addr != info->ipi_spec_dst.s_addr)
-    memcpy (&myaddr.sin_addr, &bindaddr.sin_addr,sizeof bindaddr.sin_addr);
-
-      /* Now that we have read the request packet from the UDP
-         socket, we fork and go back to listening to the socket. */
-    pid = FORK ();
-    if (pid < 0)
-           perror_msg_and_die ("cannot fork");
-    if (pid == 0)
-           break;                      /* Child exits the while(1), parent continues to loop */
-    }
+          }
+      }
+      /* Process the request */
+      myaddr.sin_family = AF_INET;
+      myaddr.sin_port = htons (0);     /* we want a new local port */
+      myaddr.sin_addr = getLanIp();
+
+#ifdef DAEMONIZE
+          if (myaddr.sin_addr.s_addr != info->ipi_spec_dst.s_addr)
+              memcpy (&myaddr.sin_addr, &bindaddr.sin_addr,sizeof bindaddr.sin_addr);
+
+          /* Now that we have read the request packet from the UDP
+             socket, we fork and go back to listening to the socket. */
+          pid = FORK ();
+
+          if (pid < 0)
+              perror_msg_and_die ("cannot fork");
+          if (pid == 0)
+              break;
+         /* Child exits the while(1), parent continues to loop */
+#endif
+  }
 
   /* Close file descriptors we don't need */
   // brcm close (fd);
@@ -770,16 +839,13 @@ tftpd_daemon (char *directory, char *address, int port)
   if (bind (peer, (struct sockaddr *) &myaddr, sizeof myaddr) < 0)
     perror_msg_and_die ("daemon-child bind");
 
-//printf("after bind. my_ip=%s*****\n", inet_ntoa(myaddr.sin_addr));
-
   if (connect (peer, (struct sockaddr *) &from, sizeof from) < 0)
     perror_msg_and_die ("daemon-child connect");
-  tp = (struct tftphdr *) buf;
 
-//printf("after connect \n");
+  tp = (struct tftphdr *) buf;
 
   int accessMode = bcmCheckEnable("tftp", from.sin_addr);
-//printf("accessmode = %d\n", accessMode);
+
   if (accessMode == CLI_ACCESS_DISABLED) 
   {
     close(peer);
@@ -795,7 +861,6 @@ tftpd_daemon (char *directory, char *address, int port)
       exit(0);
     }
   }
-//printf("socket ifname = %s\n", glbIfName);
   
   tp->th_opcode = ntohs (tp->th_opcode);
 
@@ -811,8 +876,6 @@ tftpd_daemon (char *directory, char *address, int port)
   exit (0);
 }
 
-
-
 int
 tftpd_main (int argc, char **argv)
 {
@@ -855,14 +918,13 @@ tftpd_main (int argc, char **argv)
 
   if (ioctl (fd, FIONBIO, &on) < 0)
     perror_msg_and_die ("ioctl(FIONBIO)");
-#endif //brcm
 
   /* daemonize this process */
   if (daemonize)
-    {
+  {
       pid_t f = FORK ();
       if (f > 0) {
-// brcm save the pid in the file for kill.
+        // brcm save the pid in the file for kill.
         FILE *pid_fp;
         if (!(pid_fp = fopen("/var/run/tftpd_pid", "w"))) 
         {
@@ -875,12 +937,12 @@ tftpd_main (int argc, char **argv)
       }
       if (f < 0)
        perror_msg_and_die ("cannot fork");
-#if 0 //brcm
       close (0);
       close (1);
       close (2);
+  }
 #endif //brcm
-    }
+
   result = tftpd_daemon ("", address, port);
   return (result);
 }