#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
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));
/* 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);
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);
exit(0);
}
}
-//printf("socket ifname = %s\n", glbIfName);
tp->th_opcode = ntohs (tp->th_opcode);
exit (0);
}
-
-
int
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")))
{
}
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);
}