Linux-Development-Sys Digest #922, Volume #7     Wed, 31 May 00 15:13:17 EDT

Contents:
  Problem with kernel module programming... ("Robichaud, Jean-Philippe 
[BAN:6S33:EXCH]")
  Re: Need ideas for university funded project for linux (Leslie Mikesell)
  Re: Increase the priority of a thread... how? (Tom Thorne)

----------------------------------------------------------------------------

From: "Robichaud, Jean-Philippe [BAN:6S33:EXCH]" <[EMAIL PROTECTED]>
Subject: Problem with kernel module programming...
Date: Thu, 01 Jun 2000 02:21:04 -0400

For some reason, I must program a kernel module that ping another
computer...  My problem I that if I include the netinet/ip_icmp.h file,
I get a lot of "was redifined" error and if I don't include it, I get
undefined symbol error...  Any tips ?

     thanks.


P.S., here is the entire file I'm working on... (it is not complete, but
I should work like this...)
there is some part of the code doing nothing right now, but that what
I'm working on...


/* Create a "file" in /proc for input and output... */

#include <linux/kernel.h>
#include <linux/module.h>

#if CONFIG_MODVERSIONS==1
#define MODVERSIONS
#include <linux/modversions.h>
#endif


#include <linux/proc_fs.h>
#include <asm/uaccess.h> /* for get_user & put_user */

#include <linux/sched.h>
#include <linux/tty.h>

#if(0)

#include <signal.h> 
#include <errno.h>
#include <sys/time.h>

#include <sys/param.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/file.h>

#include <netinet/in_systm.h>
#include <netinet/in.h>

#include <netinet/ip.h>


#include <netinet/ip_icmp.h>
#endif

#include <netdb.h>



void print_string(char *str);

        




#define MESSAGE_LENGTH 80
static char Message[MESSAGE_LENGTH];

static ssize_t module_output(
        struct file *file,
        char *buf, 
        size_t len,
        loff_t *offset)
{
 static int finished = 0;
 int i;
 char message[MESSAGE_LENGTH+30];

 if (finished) {
        finished=0;
        return 0;
 }

 sprintf(message,"Last input:%s",Message);
 for(i=0; i<len &&message[i];i++)
         put_user(message[i],buf+i);
 finished =1;
 return i;
}


static ssize_t module_input (
        struct file *file,
        const char *buf,
        size_t length,
        loff_t *offset)
{
 int i;

 for(i=0; i<MESSAGE_LENGTH-1 && i<length;i++)
        get_user(Message[i],buf+i);
 Message[i] = '\0';
 return i;
}


static int module_permission(struct inode *inode, int op)
{
 if(op==4|| (op== 2 && current->euid == 0))
        return 0;

 return -EACCES;
}

int module_open(struct inode *inode, struct file *file)
{
 MOD_INC_USE_COUNT;

 return 0;
}

int module_close(struct inode *inode, struct file *file)
{
 MOD_DEC_USE_COUNT;

 return 0;
}

/* structures to reguster as the /proc file with
 * pointers to all the relevant functions       */


/****************************************
 * structure File_Ops_4_Our_Proc_File   *
 *                                                                              *
 * This define each function that will  *
 * handle each action taken on the              *
 * "file"                                                               *
 *                                                                              *
 ****************************************/

static struct file_operations File_Ops_4_Our_Proc_File =
{
        NULL,                   /* lseek*/
        module_output,  /*"read" from the file*/
        module_input,   /*"write from the file*/
        NULL,                   /* readdir*/
        NULL,                   /* select*/
        NULL,                   /* ioctl*/
        NULL,                   /* mmap*/
        module_open,    /* opening the file*/
        NULL,                   /* flush*/
        module_close    /* closing the file*/
        /* there is other things /usr/include/linux/fs.h
     * but we don't need them and they are assumed as NULL */
};

/****************************************
 * structure Inode_Ops_4_Our_Proc_File  *
 *                                                                              *
 * This define each function that will  *
 * handle each action taken on the              *
 * inode                                                                *
 *                                                                              *
 ****************************************/

static struct inode_operations Inode_Ops_4_Our_Proc_File = 
{
        &File_Ops_4_Our_Proc_File,      /* functions linked to actions on the file*/
        NULL,                                           /*create*/
        NULL,                                           /*lookup*/
        NULL,                                           /*link*/
        NULL,                                           /*unlink*/
        NULL,                                           /*symlink*/
        NULL,                                           /*mkdir*/
        NULL,                                           /*rmdir*/
        NULL,                                           /*mknod*/
        NULL,                                           /*rename*/
        NULL,                                           /*readlink*/
        NULL,                                           /*follow_link*/
        NULL,                                           /*readpage*/
        NULL,                                           /*writepage*/
        NULL,                                           /*bmap*/
        NULL,                                           /*truncate*/
        module_permission                       /* ckeck for permissions*/
};

/****************************************
 * structure Our_Proc_File                              *
 *                                                                              *
 * This is our /proc directory entry    *
 * i.e. our file in /proc directory             *
 *                                                                              *
 * Contains the details of the "file"   *
 *                                                                              *
 ****************************************/

static struct proc_dir_entry Our_Proc_File = 
{
        0,                                                              /* inode 
number - ignore, it will be filled by 
                                                                         * 
proc_register[_dynamic] */
        7,                                                              /* length of 
the file name */
        "rw_test",                                      /* name of the file */
        S_IFREG | S_IRUGO | S_IWUSR,    /* file mode */
        1,                                                              /* number of 
link */
        0, 0,                                                   /* uid and gid of the 
owner (root) */
        80,                                                             /* size of 
file reported by ls */
        &Inode_Ops_4_Our_Proc_File,             /* inode structure of the file */
        NULL                                                    /* read function of 
the file (actually 
                                                                         * in 
Inode...)*/
};

/***************************************
 * Function init_module()              *
 *                                     *
 * This function is called when insmod *
 * command is run.  It register the    *
 * /proc file and return the result    *
 *                                     *
 ***************************************/

int init_module()
{
 int a; 

 char str[80];
 a = proc_register(&proc_root, &Our_Proc_File);
 sprintf(str,"return value : %d",a);    
 print_string(str);
 return a;
}

/***************************************
 * Function cleanup_module()           *
 *                                     *
 * This function is called when rmmod  *
 * command is run.  It unreguster the  *
 * /proc file                          *
 *                                     *
 ***************************************/

void cleanup_module()
{
 proc_unregister(&proc_root, Our_Proc_File.low_ino);
}

/***************************************
 * Function print_string(str)          *
 *                                     *
 * take str and prints it on the       *
 * actual console using the current    *
 * pointer and the write method.       *
 *                                     *
 * This replace printk                 *
 ***************************************/

void print_string(char *str)
{
        struct tty_struct *my_tty;
        my_tty = current->tty;

        if(my_tty != NULL) {            /* will be NULL if it's a deamon */
                (*(my_tty->driver).write)(
                        my_tty,
                        0,
                        str,
                        strlen(str));
                (*(my_tty->driver).write)( /* Add manually the newline and return */
                        my_tty,
                        0,
                        "\015\012",
                        2);
        }
} /* End of print_string() */

/*
 *                      P I N G . C
 *
 * Using the InterNet Control Message Protocol (ICMP) "ECHO" facility,
 * measure round-trip-delays and packet loss across network paths.
 *
 * Author -
 *      Mike Muuss
 *      U. S. Army Ballistic Research Laboratory
 *      December, 1983
 * Modified at Uc Berkeley
 *
 * Changed argument to inet_ntoa() to be struct in_addr instead of
u_long
 * DFM BRL 1992
 *
 * Status -
 *      Public Domain.  Distribution Unlimited.
 *
 * Bugs -
 *      More statistics could always be gathered.
 *      This program has to run SUID to ROOT to access the ICMP socket.
 */

#define MAXWAIT         5       /* max time to wait for response, sec. */
#define MAXPACKET       4096    /* max packet size */
#define VERBOSE         1       /* verbose flag */
#define QUIET           2       /* quiet flag */
#define FLOOD           4       /* floodping flag */
#define DEFAULT_PACKET_SIZE 8
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN  64
#endif

u_char  packet[MAXPACKET];
int         i, 
                pingflags, 
                options;
extern  int errno;

int                             s;                      /* Socket file descriptor */
struct hostent          *hp;            /* Pointer to host info */
struct timezone         tz;                     /* leftover */

struct sockaddr         whereto;        /* Who to ping */
int                             datalen;        /* How much data */

char usage[] = "Usage:  ping host_ip_address \n";

char *hostname;
char hnamebuf[MAXHOSTNAMELEN];

int npackets            = 3;
int ntransmitted        = 0;            /* sequence # for outbound packets = #sent */
int ident;

int nreceived           = 0;            /* # of packets we got back */
int tmin                        = 999999999;
int tmax                        = 0;
int tsum                        = 0;            /* sum of all times, for doing average 
*/
int finish(), 
        catcher();
char *inet_ntoa();

void ping(void)
{
        struct sockaddr_in from;
        struct sockaddr_in *to = (struct sockaddr_in *) &whereto;
        int on = 1;
        struct protoent *proto;

        bzero((char *)&whereto, sizeof(struct sockaddr) );
        to->sin_family = AF_INET;
        to->sin_addr.s_addr = inet_addr("47.115.51.38");
        if(to->sin_addr.s_addr != (unsigned)-1) {
                strcpy(hnamebuf, "47.115.51.38");
                hostname = hnamebuf;
        } else {
                printk(" Use numerical ip adress only\n");
                exit(1);
        }

        datalen = DEFAULT_PACKET_SIZE ;

        ident = getpid() & 0xFFFF;

        if ((proto = getprotobyname("icmp")) == NULL) {
                printk("icmp: unknown protocol\n");
                exit(10);
        }

        if ((s = socket(AF_INET, SOCK_RAW, proto->p_proto)) < 0) {
                perror("ping: socket");
                exit(5);
        }

        printk("PING %s (%s): %d data bytes\n", hostname,
                                                                                       
 inet_ntoa(to->sin_addr), 
                                                                                       
 datalen);

        signal(SIGINT, (void *) finish );
        signal(SIGALRM, (void *) catcher);

        if(!(pingflags & FLOOD))
                catcher();      /* start things going */

        for (;;) {
                int len = sizeof (packet);
                int fromlen = sizeof (from);
                int cc;
                struct timeval timeout;
                int fdmask = 1 << s;

                timeout.tv_sec = 0;
                timeout.tv_usec = 5000;

                if ( (cc=recvfrom(s, packet, len, 0, &from, &fromlen)) < 0) {
                        if( errno == EINTR ){
                                printk("pass by here\n");
                                continue;
                        }
                        perror("ping: recvfrom");
                        continue;
                }
                pr_pack( packet, cc, &from ); 
                if (npackets && nreceived >= npackets)
                        finish();
        }
        /*NOTREACHED*/
}

/*
 *                      C A T C H E R
 * 
 * This routine causes another PING to be transmitted, and then
 * schedules another SIGALRM for 1 second from now.
 * 
 */
int catcher(void)
{
        int waittime;

        pinger();
        if (npackets == 0 || ntransmitted < npackets)
                alarm(1);
        else {
                if (nreceived) {
                        waittime = 2 * tmax / 1000;
                        if (waittime == 0)
                                waittime = 1;
                } else
                        waittime = MAXWAIT;
                signal(SIGALRM, (void *) finish);
                /* if the last ping dosen't answer, finish */
                alarm(waittime); 
        }
}

/*
 *                      P I N G E R
 * 
 * Compose and transmit an ICMP ECHO REQUEST packet.  The IP packet
 * will be added on by the kernel.  The ID field is our UNIX process ID,
 * and the sequence number is an ascending integer.  The first 8 bytes
 * of the data portion are used to hold a UNIX "timeval" struct in VAX
 * byte-order, to compute the round-trip time.
 */
void pinger(void)
{
        static u_char outpack[MAXPACKET];
        register struct icmp *icp = (struct icmp *) outpack;
        int i, cc;
        register struct timeval *tp = (struct timeval *) &outpack[8];
        register u_char *datap = &outpack[8+sizeof(struct timeval)];

        icp->icmp_type = ICMP_ECHO;
        icp->icmp_code = 0;
        icp->icmp_cksum = 0;
        icp->icmp_seq = ntransmitted++;
        icp->icmp_id = ident;           /* ID */

        cc = datalen+8;                 /* skips ICMP portion */

        for( i=8; i<datalen; i++)       /* skip 8 for time */
                *datap++ = i;

        /* Compute ICMP checksum here */
        icp->icmp_cksum = in_cksum( icp, cc );

        /* cc = sendto(s, msg, len, flags, to, tolen) */
        i = sendto( s, outpack, cc, 0, &whereto, sizeof(struct sockaddr) );

        if( i < 0 || i != cc )  {
                if( i<0 )  perror("sendto");
                printk("ping: wrote %s %d chars, ret=%d\n",
                        hostname, cc, i );
        }
}

/*
 *                      P R _ T Y P E
 *
 * Convert an ICMP "type" field to a printable string.
 */
char * pr_type( t )
register int t;
{
        static char *ttab[] = {
                "Echo Reply",
                "ICMP 1",
                "ICMP 2",
                "Dest Unreachable",
                "Source Quench",
                "Redirect",
                "ICMP 6",
                "ICMP 7",
                "Echo",
                "ICMP 9",
                "ICMP 10",
                "Time Exceeded",
                "Parameter Problem",
                "Timestamp",
                "Timestamp Reply",
                "Info Request",
                "Info Reply"
        };

        if( t < 0 || t > 16 )
                return("OUT-OF-RANGE");

        return(ttab[t]);
}

/*
 *                      P R _ P A C K
 *
 * Print out the packet, if it came from us.  This logic is necessary
 * because ALL readers of the ICMP socket get a copy of ALL ICMP packets
 * which arrive ('tis only fair).  This permits multiple copies of this
 * program to be run without having intermingled output (or
statistics!).
 */
void pr_pack( buf, cc, from )
char *buf;
int cc;
struct sockaddr_in *from;
{
        struct ip *ip;
        register struct icmp *icp;
        register long *lp = (long *) packet;
        register int i;
        struct timeval tv;
        struct timeval *tp;
        int hlen, triptime;

        from->sin_addr.s_addr = ntohl( from->sin_addr.s_addr );
        gettimeofday( &tv, &tz );

        ip = (struct ip *) buf;
        hlen = ip->ip_hl << 2;

        cc -= hlen;
        icp = (struct icmp *)(buf + hlen);

        if( icp->icmp_id != ident )
                return;                 /* 'Twas not our ECHO */


        if(!(pingflags & QUIET)) {
                if(pingflags != FLOOD) {
                        printk("%d bytes from %s: icmp_seq=%d", cc,
                          inet_ntoa(from->sin_addr),
                          icp->icmp_seq );      /* DFM */
                          putchar('\n');
                } else {
                        putchar('\b');
                }
        }
        nreceived++;
}


/*
 *                      I N _ C K S U M
 *
 * Checksum routine for Internet Protocol family headers (C Version)
 *
 */
int in_cksum(addr, len)
u_short *addr;
int len;
{
        register int nleft = len;
        register u_short *w = addr;
        register u_short answer;
        register int sum = 0;

        /*
         *  Our algorithm is simple, using a 32 bit accumulator (sum),
         *  we add sequential 16 bit words to it, and at the end, fold
         *  back all the carry bits from the top 16 bits into the lower
         *  16 bits.
         */
        while( nleft > 1 )  {
                sum += *w++;
                nleft -= 2;
        }

        /* mop up an odd byte, if necessary */
        if( nleft == 1 ) {
                u_short u = 0;

                *(u_char *)(&u) = *(u_char *)w ;
                sum += u;
        }

        /*
         * add back carry outs from top 16 bits to low 16 bits
         */
        sum = (sum >> 16) + (sum & 0xffff);     /* add hi 16 to low 16 */
        sum += (sum >> 16);                     /* add carry */
        answer = ~sum;                          /* truncate to 16 bits */
        return (answer);
}

/*
 *                      F I N I S H
 *
 */
int finish(void)
{
        exit(0);
}









-- 
        Jean-Philippe Robichaud
        [EMAIL PROTECTED]
        (514) 818-7750
        St-Laurent, Quebec, Canada

------------------------------

From: [EMAIL PROTECTED] (Leslie Mikesell)
Crossposted-To: 
comp.os.linux,comp.os.linux.development,comp.os.linux.development.apps,comp.os.linux.misc,comp.os.linux.setup,comp.os.linux.advocacy
Subject: Re: Need ideas for university funded project for linux
Date: 31 May 2000 13:53:50 -0500

In article <[EMAIL PROTECTED]>,
Yarick Rastrigin  <[EMAIL PROTECTED]> wrote:

>> 
>>         Certainly. Just rebuild the db at 3am when the system is idle
>>         and the end user is asleep...
>I for myself always hate this behavior. It's not uncommon in our company
>to work through 
>the night, and updatedb slowing things down usually in the middle of
>hard debugging session
>pisses me off. And when it runs throuhg network mounts with 20 to 100
>Gb's SMB-mounted disks
>all across our local network - it's waay too long to complete, so it's
>better to 
>killall find.

Updatedb should be configured to ignore network mounts by default.
Not all distributions/versions got that right.

  Les Mikesell
   [EMAIL PROTECTED]

------------------------------

From: [EMAIL PROTECTED] (Tom Thorne)
Subject: Re: Increase the priority of a thread... how?
Date: Wed, 31 May 2000 19:06:48 GMT


>What problems are you seeing in your app to need a priority change.

I am porting a win32 app over to linux.  It has an ip message handler
thread that runs (on win32) at a higher priority than other threads in
the app.

...so I'll just try it as SCHED_OTHER and hope for the best.

Thanks


Tom Thorne <tomt at flyingpig dot com>

------------------------------


** FOR YOUR REFERENCE **

The service address, to which questions about the list itself and requests
to be added to or deleted from it should be directed, is:

    Internet: [EMAIL PROTECTED]

You can send mail to the entire list (and comp.os.linux.development.system) via:

    Internet: [EMAIL PROTECTED]

Linux may be obtained via one of these FTP sites:
    ftp.funet.fi                                pub/Linux
    tsx-11.mit.edu                              pub/linux
    sunsite.unc.edu                             pub/Linux

End of Linux-Development-System Digest
******************************

Reply via email to