[prev in list] [next in list] [prev in thread] [next in thread] 

List:       uclinux
Subject:    [UCLINUX] Re: Fixed INETD.  Plus Netburner porting...
From:       Greg Ungerer <gerg () moreton ! com ! au>
Date:       2000-06-08 1:20:03
[Download RAW message or body]

Hi Jinux Kim,

Jin-wook Kim wrote:
> With Antony's source code, now I can bootup uCLinux on my NetBurner board.
> I compared Antony's port with mine, and modified later.
> Because Antony uses CADRE-III configuration, I patch all the configuration code
> using CONFIG_NetBurner defined. It works.
> But I have still trap in inetd. I don't know why.

Rajiv recently fixed a NULL pointer problem in inetd, this is most
likely what you are seeing. Attached is a fixed version of inetd.c


> Does it comes from 'dhcpd'? I don't use dhcp and still doesn't configure eth0.
> I will try to configure eth0 manually tomorrow. I need some sleeps now.. :(

Yeah, try the manual method first.


> After some fixing, I will send my modification to you.

Yes, please do.


> And can you explain me what's the file 'ram.ld' and what does it mean?
> All the ram.ld file in platform/5206e/ subdirectories,
> ORIGIN have some offset from it's RAM starting address.
> For example, in Antony's Netburner port ORIGIN has the value 0x2020000 where
> DRAM address space start from 0x2000000.
> I can even see that in CADRE-III ORIGIN has the value 0x20000.
> What does ORIGIN and LENGTH value means?

I can explain the 0x20000 offset here. On most eval boards this region
is "reserved" for use by the built-in ROM dBUG monitor. Linux can run
and you can still debug with dBUG on most eval boards.

On boards that don't have dBUG you won't see this 0x20000 offset
from the start of RAM.
 
As Antony suggested, the doco can reveal the syntax and semantics
if you want to know more about linker scripts...


> Thanks Antony and Greg for your good works and sharing.

No worries. Please do send patches when you are done.

Seeya
Greg


------------------------------------------------------------------------
Greg Ungerer                                  EMAIL: gerg@moreton.com.au
Moreton Bay                                   PHONE:     +61 7 3279 1822
Unit 12, 97 Jijaws St,                        FAX:       +61 7 3279 1820
Sumner Park, QLD, 4074, Australia             WEB:    www.moretonbay.com
["inetd.c" (application/octet-stream)]

/* inetd.c: Start up network services
 *
 * Copyright (C) 1998  Kenneth Albanowski <kjahds@kjahds.com>
 * Copyright (C) 1999  D. Jeff Dionne     <jeff@rt-control.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */

/* Fixed Null Pointer references caused by code in read_config()
 *                    - Rajiv Dhinakaran, 1 June 2000.
 */

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <dirent.h>
#include <errno.h>
#include <string.h>
#include <termios.h>
#include <ctype.h>

#include <fcntl.h>
#include <linux/sockios.h>
#include <linux/socket.h>
#include <linux/fs.h>
#include <linux/if.h>
#include <linux/in.h>
#include <linux/icmp.h>
#include <linux/route.h>

#include <netinet/in.h>
#include <arpa/inet.h>
#include <termios.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/utsname.h>

#define MAX_SERVICES 4
#define MAX_CONNECT 8

void close_on_exec(int f)
{
	if (fcntl(f, F_SETFD, 1))
		perror("close on exec: ");
}

void close_all_fds(int keep_top)
{
	int i;
	for(i=keep_top+1;i<NR_OPEN;i++)
		close(i);
}

struct {
	int enabled;
        char *args[6];
        char arg[128];
	int port;
	int tcp;
	int reconfig;

	int master_socket;
	
	int limit;
	int current;
	int pid[16];

	int changed;
} service[MAX_SERVICES];


int reap_child(int pid) {
  int i;
  char buf[64];
  int reaped = 0;

  for(i=0;i<MAX_SERVICES;i++) {
    int j;
    for(j=0;j<16;j++)
      if (service[i].pid[j] == pid) {
        service[i].pid[j] = 0;
        service[i].current--;
      }
  }
  return reaped;
}

int generate_select_fds(fd_set * readmask, fd_set * writemask)
{
  int i;
  int max=0;
  FD_ZERO(readmask);
  FD_ZERO(writemask);
#define FD_MSET(x,y) FD_SET((x),(y)); if ((x)>max) max = (x);

  for(i=0;i<MAX_SERVICES;i++) {
    if (!strlen(service[i].args[0]) || (service[i].current >= service[i].limit))
      continue;

    FD_MSET(service[i].master_socket, readmask);

  }

  return max+1;
}

int handle_incoming_fds(fd_set * readmask, fd_set * writemask)
{
  int i;


  for(i=0;i<MAX_SERVICES;i++) {
    int fd;
    if (service[i].master_socket && FD_ISSET(service[i].master_socket, readmask)) {
      int j;
      for(j=0;j<16;j++)
        if (service[i].pid[j] == 0)
          break;

      if (service[i].tcp) {
        struct sockaddr_in remote;
        int remotelen = sizeof(remote);
        fd = accept(service[i].master_socket, (struct sockaddr*)&remote, &remotelen);
        if (fd < 0) {
          printf("accept failed\n");
          break;
        }
      } else {
        fd = service[i].master_socket;
      }

      if (!(service[i].pid[j] = vfork())) {
        if (fd != 0)
          dup2(fd, 0);
        if (fd != 1)
          dup2(fd, 1);
        if (fd != 2)
          dup2(fd, 2);
        if (fd > 2)
          close(fd);
        close_all_fds(2);
        service[i].current++;
        execlp(service[i].args[0],
	       service[i].args[0],
	       service[i].args[1],
	       service[i].args[2],
	       service[i].args[3],
	       service[i].args[4],
	       service[i].args[5],
	       NULL /* just to be safe */
	       );

        service[i].current--;
        close(service[i].master_socket);
        service[i].enabled = 0;
        service[i].master_socket = 0;
        _exit(0);
      }

      if (service[i].tcp) {
        close(fd);
      }
    }
  }
}

int start_services(void) {
  int s;
  int i;
  struct server_sockaddr;

  for(i=0;i<MAX_SERVICES;i++) {
    struct sockaddr_in server_sockaddr;

    if (service[i].master_socket || !strlen(service[i].args[0]))
      continue;

    if (service[i].tcp) {
      int true;
      
      if ((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
        printf("Unable to create socket\n");
      }

      close_on_exec(s);

      server_sockaddr.sin_family = AF_INET;
      server_sockaddr.sin_port = htons(service[i].port);
      server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
     
      true = 1;

      if((setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void *)&true, 
         sizeof(true))) == -1) {
        perror("setsockopt: ");
      }

      if(bind(s, (struct sockaddr *)&server_sockaddr, 
        sizeof(server_sockaddr)) == -1)  {
        perror("Unable to bind server socket: ");
        close(s);
      }

      if(listen(s, 1) == -1) {
        printf("Unable to listen to socket\n");
      }
    
    } else {

      if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
        printf("Unable to create socket\n");
      }

      close_on_exec(s);

      server_sockaddr.sin_family = AF_INET;
      server_sockaddr.sin_port = htons(service[i].port);
      server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);

      if(bind(s, (struct sockaddr *)&server_sockaddr,
        sizeof(server_sockaddr)) == -1)  {
        printf("Unable to bind socket\n");
        close(s);
      }
    }
    service[i].master_socket = s;
    service[i].reconfig = 1;
    service[i].changed = 0;
  }  
}

int stop_services(void) {
  int s;
  int i;
  struct server_sockaddr;
  
  for(i=0;i<MAX_SERVICES;i++) {
    if(service[i].master_socket)
      close(service[i].master_socket);
    service[i].master_socket = 0;
  }
}

void reap_children(void)
{
  int child;
  int status;
  while ((child = waitpid(-1, &status, WNOHANG)) > 0) {
    reap_child(child);
  }
}

volatile int got_hup;
void hup_handler(int signo)
{
	got_hup = 1;
	
}
volatile int got_cont;
void cont_handler()
{
	got_cont = 1;
}

void stop_handler()
{
	got_cont = 0;
	/* To reduce memory usage & prevent callers from getting gummed up */
	stop_services(); 
	while(!got_cont) {
		pause();
		reap_children();
	}
	got_cont = 0;
}

void child_handler(int signo)
{
	/* Don't reap, just interrupt the syscall */
}

char * pstrdup(char * c) {
	char * _c = c;
	if (_c)
		_c = strdup(_c);
	return _c;
}

void kill_changed_things(void)
{
	int i;

	for(i=0;i<MAX_SERVICES;i++) {
		int j;

		if (!service[i].changed || !service[i].reconfig)
			continue;
		
		if (service[i].master_socket) {
			close(service[i].master_socket);
			service[i].master_socket = 0;
		}

		for (j=0;j<16;j++) {
			if (service[i].pid[j] != 0) {
				kill(service[i].pid[j], SIGTERM);
				kill(service[i].pid[j], SIGHUP);
				service[i].pid[j] = 0;
			}
		}
		service[i].changed = service[i].reconfig = 0;
	}
}

void run(void)
{
  fd_set rfds, wfds;
  struct timeval tv;
  int max;
  for(;;) {
    reap_children();
    start_services();

    max = generate_select_fds(&rfds, &wfds);
    tv.tv_sec = 1;
    tv.tv_usec = 0;
    if (select(max, &rfds, &wfds, 0, &tv) > 0) {
      handle_incoming_fds(&rfds, &wfds);
    }
    if (got_hup) {
    	got_hup = 0;
	read_config();
    	kill_changed_things();
    	continue;
    }
  }
}

/* Very simple file format, lines of the form
 * port# ignored tcp/udp ignored ignored <exec path> args...
 * this should be compatible with berkeley derived inetd
 */
int
read_config()
{
  FILE *cfp;
  FILE *sfp;
  char **args;
  char *ap;

  int i, j, k;

  if (!(cfp = fopen(INETD_CONF,"r"))) {
    perror("Can't open " INETD_CONF);
    exit(1);
  }

  if (!(sfp = fopen(SERVICES,"r"))) {
    perror("Can't open " SERVICES);
    fclose(cfp);
    exit(1);
  }

  for (i=0; i<MAX_SERVICES; i++) {            //
    service[i].arg[0]=0;                      // Fixup for NULL PTR
    service[i].args[0]=service[i].arg;        //       - Rajiv
  }

  for (i=0; i<MAX_SERVICES;) {
    if (!(args = cfgread(cfp))) break;

    for (j=0; (j<11) && (args[j]); j++);
    if (j<6) {
      fprintf(stderr,"Bad line in config file %s...\n",
	      args[0] ? args[0] : "");
      continue;
    }

    /* copy in the args and exec path. */
    service[i].args[j - 5] = NULL;
    ap = service[i].arg;

    for (k=5; k<j; k++) {                       //
      service[i].args[k - 5] = ap;              //
      if (args[k]) {                            // Fixup for NULL PTR
        strncpy(ap, args[k], 32);               //      - Rajiv
        ap += strlen(args[k]);                  //
      }                                         //
      ap[0]=0;                                  //
      ap++;                                     //
      /* FIXME: bounds check */
    }

    service[i].tcp = !strcmp(args[2], "tcp") ? 1 : 0;

    if (!(args = cfgfind(sfp, args[0]))) {
      fprintf(stderr, "can't find service\n");
      continue;
    }

    service[i].port = atoi(args[1]);

    service[i].master_socket = 0;
    service[i].limit = MAX_CONNECT;
    service[i].changed = 1;
    service[i].enabled = 1;

#ifdef DEBUG
    printf("service %s port %d %s %s\n",
	   service[i].args[0],
	   service[i].port,
	   service[i].tcp ? "tcp" : "udp",
	   service[i].enabled ? "enabled" : "disabled");
#endif
    i++;
  }

  fclose(sfp);
  fclose(cfp);
  return i;
}

main(int argc, char *argv[], char *env[])
{
#ifdef EMBED
  __signal(SIGPIPE, SIG_IGN, 0);
  __signal(SIGSTOP, stop_handler, 0);
  __signal(SIGTSTP, stop_handler, 0);
  __signal(SIGCONT, cont_handler, 0);
  __signal(SIGCHLD, child_handler, SA_INTERRUPT);
  __signal(SIGHUP, hup_handler, 0);
#endif  

  read_config();

  run();
  
  /* not reached */
}


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic