identd

Kreuzuebersetzer, Diskussion über Änderungen im Tuxbox-CDK und Tuxbox-CVS
Ryker
Image-Team
Beiträge: 554
Registriert: Montag 2. Juni 2003, 10:38

identd

Beitrag von Ryker »

Damit ich im IRC unrestricted bin, möchte ich mir auf meiner dbox einen identd laufen lassen und dann am DSL-Router eine NAT-Portumleitung für Port 113 einrichten. Das klappt auch wunderbar nur habe ich ein Problem. Linke ich den identd dynamisch, dann ist das binary mit 19kb auch schön klein, aber es fehlt in der /lib/libc.so.6 die Funktionen "htons()", da die libc ja gestript ins dbox-Image wandert.
Linke ich den identd statisch, dann hat der nach dem strippen immernoch die Größe von 465kb und ich kann es nur nach /tmp kopieren und dort ausführen.

Hat jemand eine Idee, was ich da tun kann ?

Ryker
D-Box2 (Nokia; Kabel; 2xINTEL; AVIA500) - aktuelles JtG-Image
Barf
Developer
Beiträge: 1475
Registriert: Dienstag 4. Februar 2003, 22:02

Beitrag von Barf »

Eigene Image bauen? Yadd Benutzen? Statisches binary auf NFS-Platte, oder SD-Karte, oder IDE-Platte?

Natürlich wäre es auch denkbar, htons statisch einzubinden, sonst dynamisch gegen libc.so zu linken.
Ryker
Image-Team
Beiträge: 554
Registriert: Montag 2. Juni 2003, 10:38

Beitrag von Ryker »

Barf hat geschrieben:Eigene Image bauen? Yadd Benutzen? Statisches binary auf NFS-Platte, oder SD-Karte, oder IDE-Platte?
Die Varianten sind mir klar.
Barf hat geschrieben: Natürlich wäre es auch denkbar, htons statisch einzubinden, sonst dynamisch gegen libc.so zu linken.
Aber hier wird es schon interessanter. Ich habe bisher nicht gewußt, daß sowas auch geht. Muß ich mal probiern.

Danke!
D-Box2 (Nokia; Kabel; 2xINTEL; AVIA500) - aktuelles JtG-Image
Ryker
Image-Team
Beiträge: 554
Registriert: Montag 2. Juni 2003, 10:38

Beitrag von Ryker »

Ryker hat geschrieben:
Barf hat geschrieben: Natürlich wäre es auch denkbar, htons statisch einzubinden, sonst dynamisch gegen libc.so zu linken.
Aber hier wird es schon interessanter. Ich habe bisher nicht gewußt, daß sowas auch geht. Muß ich mal probiern.
So, nun habe ich dem man-pages vom gcc von oben bis unten mehrmals durchgeschaut, aber keine Option gefunden, mit der ich einzelne Funktionen aus Libraries statisch linken kann - hat jemand eine Beispiel parat ?

Ryker
D-Box2 (Nokia; Kabel; 2xINTEL; AVIA500) - aktuelles JtG-Image
Houdini
Developer
Beiträge: 2183
Registriert: Mittwoch 10. Dezember 2003, 07:59

Beitrag von Houdini »

nicht beim gcc, sondern beim linker müsstest du suchen
Barf
Developer
Beiträge: 1475
Registriert: Dienstag 4. Februar 2003, 22:02

Beitrag von Barf »

Eine besonderes einfache Methode kenne ich nicht. So hier wurde ich machen (vielleicht gibt es bessere Vorgehen):

Finde raus in welchen File (von glibc) htons definiert wird. (Dazu die glibc-Source entpacken.) Kompiliere -- irgendwie -- dieses File, und binde die entsprechende *.o-File ein bei Linken. Alternativ, extrahiere diese aus dem statischen libc.a mit ar. Sobald du diese o-Datei hast, kannst du auch ein mini-Library bastelt (ar), die nur aus diesem File besteht, und beim Linken einbinden.

Falls du dies machst, wirst du möglicherweise erfahren, dass diese Datei andere Symbolen referenziert. Dann wende diese Prozedur an rekursiv. :wink:

Falls es einfacher ist, als eine Image zu bauen, sei hingestellt. :wink:
Ryker
Image-Team
Beiträge: 554
Registriert: Montag 2. Juni 2003, 10:38

Beitrag von Ryker »

Barf hat geschrieben:...
Falls es einfacher ist, als eine Image zu bauen, sei hingestellt.
Wenn ich 450kb binary mit ins squashfs reinpacke, isses vermutlich gleich voll - wenns überhaupt noch reingeht, denn komprimiert sind es immernoch 210kb.
Das mit dem rausextrahieren muß ich mal bei Gelegenheit tun. Vorerst liegt das statisch gelinkte binary aufm NFS-Share und wird in die rcS.local eingebunden mit

Code: Alles auswählen

/bin/sh -c "sleep 60;/mnt/filme/identd --userid irc-username" &
Hier ist noch der Sourcecode, falls jemand interesse hat. Den habe ich so im Internet gefunden.

Code: Alles auswählen

/*
I wrote an auth daemon for winders a while ago, then lost the source.
People kept bugging me about it, so in some spare time I hacked this up.
For all it counts, it's under the latest GNU license.

I used gnu-win32 beta 19.1 by Cygnus.  To build a daemon that goes in
the background, type:
gcc -Wl,--subsystem,windows -O3 -s -o identd.exe identd.c

compile time options:
To disable command line options      -DARGLESS

-Ben

Fixed by Gena Svarovski (svarovsk@inp.nsk.su)
09/05/98
*/

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h> 
#include <sys/time.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <time.h>
#include <dirent.h>
#include <unistd.h>
#include <ctype.h>
#include <string.h>

#define VERSION "version 2.11"

/*
fd_setsize  how many file descriptors can be help in a 
file descriptor set.  We use select on a set of file descriptors to wait 
for, so we don't want to open more sockets than we make room for here.
*/
#ifndef FD_SETSIZE
#define FD_SETSIZE 256
#endif

#define ARR_SIZE 1024   /* generic string/buffer length */
#define MAX_USERS 50    /* MAX_USERS must NOT be > FD_SETSIZE - 1 */
#define ALARM_TIME 30   /* alarm time in seconds (must not exceed 60) */
#define TIME_OUT 180    /* login timeout in sec - can't be < ALARM_TIME */
#define PORT 113        /* tcp port to listen to */

#define USERVAR         "USERNAME" /* environment variable for userid */

typedef struct {
 void *next;            /* next connection in the list */
 char buffer[ARR_SIZE], /* input buffer */
      site[80];         /* remote site for this connection */
 int  sock,             /* socket handle */
      port,             /* remote tcp port for this connection */
      bufpos,
      last_input;       /* last input time, so we can disconnect idle connections */
} CONNECTION;

CONNECTION *head=NULL,  /* the beginning of the list of connections */
           *tail=NULL;  /* the end of the list of connections */

char mess[ARR_SIZE],    /* functions use mess to send output */ 
     mess2[ARR_SIZE],   /* for event functions output */
     start_time[30],    /* startup time */
     syslog_name[80],   /* syslog filename */
     localhost[80];     /* local hostname */

int  connect_count=0,   /* count of connections */
     timestamp_on=1,    /* whether to timestamp syslog entries or not */
     connect_str_size=0;/* size of CONNECTION structure */

/* prototypes */
void *create_user(void);
char *inet_ntoa();
void strtolower(char *);
void write_syslog(char *);
void check_timeout(void);
void sigcall(void);
void reset_alarm(void);
void user_quit(CONNECTION *);
void write_connection(CONNECTION *, char *);


int main(int argc, char *argv[])
{

struct sockaddr_in  bind_addr,
                    acc_addr;
struct hostent      *host;
fd_set              readmask;
unsigned int        addr;
int                 listen_sock,
                    accept_sock,
                    len,
                    on,
                    i,
                    k,
                    size,
                    port1,
                    port2,
                    resolv_for_log=1,
                    case_mangle=0;

char                inpstr[ARR_SIZE],
                    site_num[80],
                    userid[512],
                    osname[513],
                    *cp;

unsigned char       c;
CONNECTION          *user;
time_t              tm,
                    oldtm;


/* initiallize some variables */
memset(syslog_name, 0, sizeof(syslog_name));
strcpy(osname, "UNIX");
size=sizeof(struct sockaddr_in);
connect_str_size=sizeof(CONNECTION);

/* get environment information */
if (getenv(USERVAR)!=NULL) strncpy(userid, getenv(USERVAR), 512);
 else strcpy(userid, "unknown");

#ifndef ARGLESS
/* parse command line */
for (i=1; i<argc; i++) {
 if (i+1<argc) {
  if (!strcmp(argv[i], "--userid"))    { strncpy(userid, argv[++i], 512);     continue; }
  if (!strcmp(argv[i], "--osname"))    { strncpy(osname, argv[++i], 512);     continue; }
  if (!strcmp(argv[i], "--logfile"))   { strncpy(syslog_name, argv[++i], 79); continue; }
  if (!strcmp(argv[i], "--noresolv"))  { resolv_for_log=0; continue; }
  if (!strcmp(argv[i], "--lowercase")) { case_mangle=1; continue; }
 }
 printf("%s %s\n", argv[0], VERSION);
 puts(" --userid <userid>\tSets the userid identd will reply.");
 puts(" --osname <osname>\tSets the operating system name identd will reply.");
 puts(" --logfile <filename>\tSets logging on, and specifies which file to log to.");
 puts(" --noresolv\t\tDo not resolve the remote host for the logs.");
 exit(1);
}
#endif

if (case_mangle) strtolower(userid);
if (!syslog_name[0]) resolv_for_log=0;

/* get local hostname */
 gethostname(localhost, sizeof(localhost)-1);
 strtolower(localhost);

 if ((listen_sock=socket(AF_INET, SOCK_STREAM, 0))==-1) {
  write_syslog("FAIL: Couldn't open listen socket\r\n");
  exit(1);
 }

 /* Allow reboots even with TIME_WAITS etc on port */
 on=1;
 setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));

 bind_addr.sin_family=AF_INET;
 bind_addr.sin_addr.s_addr=INADDR_ANY;
 bind_addr.sin_port=htons(PORT);
 if (bind(listen_sock, (struct sockaddr *)&bind_addr, size)==-1) {
  write_syslog("FAIL: Couldn't bind to port\r\n");
  exit(1);
 }
 if (listen(listen_sock, 20)==-1) {
  write_syslog("FAIL: Listen error\r\n");
  exit(1);
 }

 /* Set socket to non-blocking. Not really needed but it does no harm. */
 fcntl(listen_sock, F_SETFL, O_NDELAY);

 oldtm=time((time_t *)0);

 sprintf(mess, "Turtle identd %s started on %s PID %d\r\n", VERSION, localhost, getpid());
 write_syslog(mess);

 /**** Main program loop. *****/
 while ( 1 ) {
  FD_ZERO(&readmask);

  for (user=head; user!=NULL; user=user->next) 
   if (user->sock!=-1) FD_SET(user->sock, &readmask);
  FD_SET(listen_sock, &readmask);

  /* wait (assumes errors are nice and not nasty) */
  if ( select(FD_SETSIZE, &readmask, 0, 0, NULL) == -1 ) continue;

  /* check for connection to listen socket */
  if ( FD_ISSET(listen_sock, &readmask) ) {
   accept_sock=accept(listen_sock, (struct sockaddr *)&acc_addr, &size);
 
   if ((user=create_user())==NULL) {
    write_syslog("ERROR: Reached connection limit.\r\n");
    close(accept_sock);
    continue;
   }

   /* get remote internet site */
   strcpy(site_num, inet_ntoa(acc_addr.sin_addr));
   addr=inet_addr(site_num);
   strcpy(user->site, site_num);
   if (resolv_for_log)
    if ((host=gethostbyaddr((char *)&addr, 4, AF_INET)))
     strncpy(user->site, host->h_name, 79);

   strtolower(user->site);
   user->port=(unsigned int)ntohs(acc_addr.sin_port);

   user->sock=accept_sock;
   user->last_input=time((time_t *)0);
  }

  /* Check to see if any of the connections timed out */
  tm=time((time_t *)0);
  if ((tm-oldtm)>ALARM_TIME) {
   oldtm=tm;
   check_timeout();
   continue;
  }

  /** cycle through connections **/
  user = head;
  while (user!=NULL) {

   for (user=head; user!=NULL; user=user->next) {

    /* if no data waiting on socket, go to the next socket */
    if (!FD_ISSET(user->sock, &readmask)) continue;
   
    /* see if client has closed socket */
    inpstr[0]=0;
    if (!(len=read(user->sock, inpstr, sizeof(inpstr)))) {
     user_quit(user);
     break;
    }



    user->last_input=time((time_t *)0);  /* ie now */

    k=user->bufpos;
    for (i=0; i<len; ++i) {
     c=(unsigned char)inpstr[i];

     /* handle eol */
     if ( c=='\n' || c=='\r' || !c || k+5>=ARR_SIZE ) goto GOT_LINE;

     /* handle non 7-bit ascii chars (not RFC compliant) */
     /* if ( c<32 || c>126 ) continue; */

     /* copy the char into buffer */
     user->buffer[k++]=c;
    }
    user->bufpos=k;
    continue;

    GOT_LINE: 
    if (k+5>ARR_SIZE) {
     sprintf(mess, "1, 1: ERROR : UNKNOWN-ERROR\r\n");
     write_connection(user, mess);
     sprintf(mess, "ERROR: %s overflowed the buffer\r\n", user->site);
     write_syslog(mess);
     user_quit(user);
     break;
    }

    user->buffer[k]='\0';
    port1=0;
    port2=0;
    for (cp=user->buffer; *cp && *cp!=','; cp++);
    if (*cp) {
     *cp='\0';
     port1=atoi(user->buffer);
     port2=atoi(cp+1);
    }
 
    if (!port1 || !port2 || (unsigned)port1>65535 || (unsigned)port2>65535) {
     sprintf(mess, "%d, %d : ERROR : INVALID-PORT\r\n", port1, port2);
     write_connection(user, mess);
     sprintf(mess, "ERROR: %s invalid port %d, %d\r\n", user->site, port1, port2);
     write_syslog(mess);
     user_quit(user);
     break;
    }   
   
    /* here we could do stuff */
    sprintf(mess, "%d, %d : USERID : %s : %s\r\n", port1, port2, osname, userid);
    write_connection(user, mess);
    sprintf(mess, "GOOD: success for %s on ports %d, %d\r\n", user->site, port1, port2);
    write_syslog(mess);
    user_quit(user);
    break;
   }
  }
 }
} /* end of main() */


/* -----
 * user_quit(CONNECTION *user)
 * closes the connection and removes it from the list
 *
*/

void user_quit(CONNECTION *user)
{
CONNECTION *i, *j;

 if (user==NULL) return;
 if (user->sock>-1) close(user->sock);
 if (user==head) {
  if (tail==head) {
   head=NULL;
   tail=NULL;
   free(user);
   return;
  }
  head=head->next;
  free(user);
  return;  
 }
 for (i=head; i->next!=user && i->next!=NULL; i=i->next);
 j=i->next;
 if (j!=user) {
  write_syslog("ERROR: Programmer error: Connection list is corrupted.\r\n");
  exit(1);
 }
 if (j==tail) tail=i;
 i->next=j->next;
 j->next=NULL;
 free(user);
 return;
}

/* -----
 * void *create_user()
 * allocates some space for the user and puts it on the list
 *
*/
void *create_user(void) {
CONNECTION *new_user;

 if (head==NULL) {
  head=malloc(connect_str_size);
  if (head==NULL) return NULL;
  memset(head, 0, connect_str_size);
  tail=head;
  head->next=NULL;
  return head;
 }

 new_user=malloc(connect_str_size);
 if (new_user==NULL) return NULL;
 memset(new_user, 0, connect_str_size);
 tail->next=new_user;
 new_user->next=NULL;
 tail=new_user;
 return new_user;
}

/* -----
 * strtolower(char *str)
 * strtolower() converts str to lowercase
 *
*/
void strtolower(char *str)
{
 if (str==NULL) return;
 while (*str) {
  *str=tolower(*str);
  str++;
 }
}


/*** Send a string to system log ***/
void write_syslog(char *str)
{
FILE *fp;
time_t tm;
char timestr[40];

 if (!syslog_name[0] || !(fp=fopen(syslog_name, "a"))) return;
 if (timestamp_on) {
  time(&tm);
  strcpy(timestr, ctime(&tm));
  timestr[strlen(timestr)-1]='\0';
  fprintf(fp, "%s: %s", timestr, str);
 } else fputs(str, fp);
 fclose(fp);
}


/*** send string down socket ***/
void write_connection(CONNECTION *user, char *str)
{
 if (user==NULL) return;
 if (user->sock>-1) write(user->sock, str, strlen(str));
}


void check_timeout(void)
{
CONNECTION *user;
int secs;

 user=head;
 while (user!=NULL) {
  for (user=head; user!=NULL; user=user->next) {
   secs=(int)time((time_t *)0)-user->last_input;
   if (secs>=TIME_OUT) {
    sprintf(mess, "ERROR: %s timed out\r\n", user->site);
    write_syslog(mess);
    user_quit(user);
    break;
   }
  }
 }
}  
D-Box2 (Nokia; Kabel; 2xINTEL; AVIA500) - aktuelles JtG-Image
Npq
Senior Member
Beiträge: 1339
Registriert: Donnerstag 24. April 2003, 12:12

Beitrag von Npq »

Hmm, da die dbox2 auf einem PowerPC basiert und somit eine bigendian Plattform ist, sollte htons(x) einfach Identität sein.

Mit anderen Worten:

Code: Alles auswählen

#define htons(x) (x)
Wieso dann allerdings trotzdem das Symbol in der ausführbaren Datei auftaucht kann ich so nicht sagen, das müßte man genauer verfolgen.
Npq
Senior Member
Beiträge: 1339
Registriert: Donnerstag 24. April 2003, 12:12

Beitrag von Npq »

Hast du evtl. ohne Optimierung kompiliert?

Probier mal:
powerpc-tuxbox-linux-gnu-gcc -O2 -s -o identd identd.c
Barf
Developer
Beiträge: 1475
Registriert: Dienstag 4. Februar 2003, 22:02

Beitrag von Barf »

Ryker hat geschrieben:Wenn ich 450kb binary mit ins squashfs reinpacke, isses vermutlich gleich voll - wenns überhaupt noch reingeht, denn komprimiert sind es immernoch 210kb.
Um nur Sachen richtigzustellen: Falls du dein identd in dem Imagebuilprozess integrierst (z.B. root-local.sh in newmake) wir benötigte symbolen (htons) beim Library Reduction nicht weggestrippt, und dein dynamisch gelinkte 19kB-identd in Image funktioniert.

Übrigens gilt dynamisch Linking gegen libc als schlecht.
woglinde
Einsteiger
Einsteiger
Beiträge: 261
Registriert: Donnerstag 15. November 2001, 00:00

Beitrag von woglinde »

Barf hat geschrieben: Übrigens gilt dynamisch Linking gegen libc als schlecht.
Aeh??? dann funktioiniert aber nix wenn du nicht gegen libc linkst.

Gruss woglinde
Barf
Developer
Beiträge: 1475
Registriert: Dienstag 4. Februar 2003, 22:02

Beitrag von Barf »

woglinde hat geschrieben:
Barf hat geschrieben: Übrigens gilt dynamisch Linking gegen libc als schlecht.
Aeh??? dann funktioiniert aber nix wenn du nicht gegen libc linkst.

Gruss woglinde
Ooops, :oops:, soll natürlich heissen "Übrigens gilt statische Linking gegen libc als schlecht." (Das Thema war früher diskutiert.)