!C99Shell v. 1.0 pre-release build #13!

Software: Apache/2.0.54 (Unix) mod_perl/1.99_09 Perl/v5.8.0 mod_ssl/2.0.54 OpenSSL/0.9.7l DAV/2 FrontPage/5.0.2.2635 PHP/4.4.0 mod_gzip/2.0.26.1a 

uname -a: Linux snow.he.net 4.4.276-v2-mono-1 #1 SMP Wed Jul 21 11:21:17 PDT 2021 i686 

uid=99(nobody) gid=98(nobody) groups=98(nobody) 

Safe-mode: OFF (not secure)

/usr/src/linux-2.4.18-xfs-1.1/drivers/net/wan/   drwxr-xr-x
Free 318.38 GB of 458.09 GB (69.5%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Feedback    Self remove    Logout    


Viewing file:     comx.c (28.51 KB)      -rw-r--r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/*
 * Device driver framework for the COMX line of synchronous serial boards
 * 
 * for Linux kernel 2.2.X
 *
 * Original authors:  Arpad Bakay <bakay.arpad@synergon.hu>,
 *                    Peter Bajan <bajan.peter@synergon.hu>,
 * Previous maintainer: Tivadar Szemethy <tiv@itc.hu>
 * Current maintainer: Gergely Madarasz <gorgo@itc.hu>
 *
 * Copyright (C) 1995-1999 ITConsult-Pro Co.
 *
 * Contributors:
 * Arnaldo Carvalho de Melo <acme@conectiva.com.br> (0.85)
 *
 * 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.
 *
 * Version 0.80 (99/06/11):
 *        - clean up source code (playing a bit of indent)
 *        - port back to kernel, add support for non-module versions
 *        - add support for board resets when channel protocol is down
 *        - reset the device structure after protocol exit
 *          the syncppp driver needs it
 *        - add support for /proc/comx/protocols and 
 *          /proc/comx/boardtypes
 *
 * Version 0.81 (99/06/21):
 *        - comment out the board reset support code, the locomx
 *          driver seems not buggy now
 *        - printk() levels fixed
 *
 * Version 0.82 (99/07/08):
 *        - Handle stats correctly if the lowlevel driver is
 *          is not a comx one (locomx - z85230)
 *
 * Version 0.83 (99/07/15):
 *        - reset line_status when interface is down
 *
 * Version 0.84 (99/12/01):
 *        - comx_status should not check for IFF_UP (to report
 *          line status from dev->open())
 *
 * Version 0.85 (00/08/15):
 *         - resource release on failure in comx_mkdir
 *         - fix return value on failure at comx_write_proc
 *
 * Changed      (00/10/29, Henner Eisen):
 *         - comx_rx() / comxlapb_data_indication() return status.
 */

#define VERSION "0.85"

#include <linux/config.h>
#include <linux/module.h>
#include <linux/version.h>

#include <linux/types.h>
#include <linux/sched.h>
#include <linux/netdevice.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
#include <linux/ctype.h>
#include <linux/init.h>

#ifdef CONFIG_KMOD
#include <linux/kmod.h>
#endif

#ifndef CONFIG_PROC_FS
#error For now, COMX really needs the /proc filesystem
#endif

#include <net/syncppp.h>
#include "comx.h"

MODULE_AUTHOR("Gergely Madarasz <gorgo@itc.hu>");
MODULE_DESCRIPTION("Common code for the COMX synchronous serial adapters");
MODULE_LICENSE("GPL");

extern int comx_hw_comx_init(void);
extern int comx_hw_locomx_init(void);
extern int comx_hw_mixcom_init(void);
extern int comx_proto_hdlc_init(void);
extern int comx_proto_ppp_init(void);
extern int comx_proto_syncppp_init(void);
extern int comx_proto_lapb_init(void);
extern int comx_proto_fr_init(void);

static struct comx_hardware *comx_channels = NULL;
static struct comx_protocol *comx_lines = NULL;

static int comx_mkdir(struct inode *, struct dentry *, int);
static int comx_rmdir(struct inode *, struct dentry *);
static struct dentry *comx_lookup(struct inode *, struct dentry *);

static struct inode_operations comx_root_inode_ops = {
    lookup:    comx_lookup,
    mkdir: comx_mkdir,
    rmdir: comx_rmdir,
};

static int comx_delete_dentry(struct dentry *dentry);
static struct proc_dir_entry *create_comx_proc_entry(char *name, int mode,
    int size, struct proc_dir_entry *dir);

static struct dentry_operations comx_dentry_operations = {
    d_delete:    comx_delete_dentry,
};


static struct proc_dir_entry * comx_root_dir;

struct comx_debugflags_struct    comx_debugflags[] = {
    { "comx_rx",        DEBUG_COMX_RX        },
    { "comx_tx",         DEBUG_COMX_TX        },
    { "hw_tx",        DEBUG_HW_TX        },
    { "hw_rx",         DEBUG_HW_RX        },
    { "hdlc_keepalive",    DEBUG_HDLC_KEEPALIVE    },
    { "comxppp",        DEBUG_COMX_PPP        },
    { "comxlapb",        DEBUG_COMX_LAPB        },
    { "dlci",        DEBUG_COMX_DLCI        },
    { NULL,            0            } 
};


int comx_debug(struct net_device *dev, char *fmt, ...)
{
    struct comx_channel *ch = dev->priv;
    char *page,*str;
    va_list args;
    int len;

    if (!ch->debug_area) return 0;

    if (!(page = (char *)__get_free_page(GFP_ATOMIC))) return -ENOMEM;

    va_start(args, fmt);
    len = vsprintf(str = page, fmt, args);
    va_end(args);

    if (len >= PAGE_SIZE) {
        printk(KERN_ERR "comx_debug: PANIC! len = %d !!!\n", len);
        free_page((unsigned long)page);
        return -EINVAL;
    }

    while (len) {
        int to_copy;
        int free = (ch->debug_start - ch->debug_end + ch->debug_size) 
            % ch->debug_size;

        to_copy = min_t(int, free ? free : ch->debug_size, 
                  min_t(int, ch->debug_size - ch->debug_end, len));
        memcpy(ch->debug_area + ch->debug_end, str, to_copy);
        str += to_copy;
        len -= to_copy;
        ch->debug_end = (ch->debug_end + to_copy) % ch->debug_size;
        if (ch->debug_start == ch->debug_end) // Full ? push start away
            ch->debug_start = (ch->debug_start + len + 1) % 
                    ch->debug_size;
        ch->debug_file->size = (ch->debug_end - ch->debug_start +
                    ch->debug_size) % ch->debug_size;
    } 

    free_page((unsigned long)page);
    return 0;
}

int comx_debug_skb(struct net_device *dev, struct sk_buff *skb, char *msg)
{
    struct comx_channel *ch = dev->priv;

    if (!ch->debug_area) return 0;
    if (!skb) comx_debug(dev, "%s: %s NULL skb\n\n", dev->name, msg);
    if (!skb->len) comx_debug(dev, "%s: %s empty skb\n\n", dev->name, msg);

    return comx_debug_bytes(dev, skb->data, skb->len, msg);
}

int comx_debug_bytes(struct net_device *dev, unsigned char *bytes, int len, 
        char *msg)
{
    int pos = 0;
    struct comx_channel *ch = dev->priv;

    if (!ch->debug_area) return 0;

    comx_debug(dev, "%s: %s len %d\n", dev->name, msg, len);

    while (pos != len) {
        char line[80];
        int i = 0;

        memset(line, 0, 80);
        sprintf(line,"%04d ", pos);
        do {
            sprintf(line + 5 + (pos % 16) * 3, "%02x", bytes[pos]);
            sprintf(line + 60 + (pos % 16), "%c", 
                isprint(bytes[pos]) ? bytes[pos] : '.');
            pos++;
        } while (pos != len && pos % 16);

        while ( i++ != 78 ) if (line[i] == 0) line[i] = ' ';
        line[77] = '\n';
        line[78] = 0;
    
        comx_debug(dev, "%s", line);
    }
    comx_debug(dev, "\n");
    return 0;
}

static void comx_loadavg_timerfun(unsigned long d)
{
    struct net_device *dev = (struct net_device *)d;
    struct comx_channel *ch = dev->priv;

    ch->avg_bytes[ch->loadavg_counter] = ch->current_stats->rx_bytes;
    ch->avg_bytes[ch->loadavg_counter + ch->loadavg_size] = 
        ch->current_stats->tx_bytes;

    ch->loadavg_counter = (ch->loadavg_counter + 1) % ch->loadavg_size;

    mod_timer(&ch->loadavg_timer,jiffies + HZ * ch->loadavg[0]);
}

#if 0
static void comx_reset_timerfun(unsigned long d)

    struct net_device *dev = (struct net_device *)d;
    struct comx_channel *ch = dev->priv;

    if(!(ch->line_status & (PROTO_LOOP | PROTO_UP))) {
        if(test_and_set_bit(0,&ch->reset_pending) && ch->HW_reset) {
            ch->HW_reset(dev);
        }
    }

    mod_timer(&ch->reset_timer, jiffies + HZ * ch->reset_timeout);
}
#endif                                            

static int comx_open(struct net_device *dev)
{
    struct comx_channel *ch = dev->priv;
    struct proc_dir_entry *comxdir = ch->procdir->subdir;
    int ret=0;

    if (!ch->protocol || !ch->hardware) return -ENODEV;

    if ((ret = ch->HW_open(dev))) return ret;
    if ((ret = ch->LINE_open(dev))) { 
        ch->HW_close(dev); 
        return ret; 
    };

    for (; comxdir ; comxdir = comxdir->next) {
        if (strcmp(comxdir->name, FILENAME_HARDWARE) == 0 ||
           strcmp(comxdir->name, FILENAME_PROTOCOL) == 0)
            comxdir->mode = S_IFREG | 0444;
    }

#if 0
    ch->reset_pending = 1;
    ch->reset_timeout = 30;
    ch->reset_timer.function = comx_reset_timerfun;
    ch->reset_timer.data = (unsigned long)dev;
    ch->reset_timer.expires = jiffies + HZ * ch->reset_timeout;
    add_timer(&ch->reset_timer);
#endif

    return 0;
}

static int comx_close(struct net_device *dev)
{
    struct comx_channel *ch = dev->priv;
    struct proc_dir_entry *comxdir = ch->procdir->subdir;
    int ret = -ENODEV;

    if (test_and_clear_bit(0, &ch->lineup_pending)) {
        del_timer(&ch->lineup_timer);
    }

#if 0    
    del_timer(&ch->reset_timer);
#endif

    if (ch->init_status & LINE_OPEN && ch->protocol && ch->LINE_close) {
        ret = ch->LINE_close(dev);
    }

    if (ret) return ret;

    if (ch->init_status & HW_OPEN && ch->hardware && ch->HW_close) {
        ret = ch->HW_close(dev);
    }
    
    ch->line_status=0;

    for (; comxdir ; comxdir = comxdir->next) {
        if (strcmp(comxdir->name, FILENAME_HARDWARE) == 0 ||
            strcmp(comxdir->name, FILENAME_PROTOCOL) == 0)
            comxdir->mode = S_IFREG | 0644;
    }

    return ret;
}

void comx_status(struct net_device *dev, int status)
{
    struct comx_channel *ch = dev->priv;

#if 0
    if(status & (PROTO_UP | PROTO_LOOP)) {
        clear_bit(0,&ch->reset_pending);
    }
#endif

    printk(KERN_NOTICE "Interface %s: modem status %s, line protocol %s\n",
            dev->name, status & LINE_UP ? "UP" : "DOWN", 
            status & PROTO_LOOP ? "LOOP" : status & PROTO_UP ? 
            "UP" : "DOWN");
    
    ch->line_status = status;
}

static int comx_xmit(struct sk_buff *skb, struct net_device *dev)
{
    struct comx_channel *ch = dev->priv;
    int rc;

    if (skb->len > dev->mtu + dev->hard_header_len) {
        printk(KERN_ERR "comx_xmit: %s: skb->len %d > dev->mtu %d\n", dev->name,
        (int)skb->len, dev->mtu);
    }
    
    if (ch->debug_flags & DEBUG_COMX_TX) {
        comx_debug_skb(dev, skb, "comx_xmit skb");
    }
    
    rc=ch->LINE_xmit(skb, dev);
//    if (!rc) dev_kfree_skb(skb);

    return rc;
}

static int comx_header(struct sk_buff *skb, struct net_device *dev, 
    unsigned short type, void *daddr, void *saddr, unsigned len) 
{
    struct comx_channel *ch = dev->priv;

    if (ch->LINE_header) {
        return (ch->LINE_header(skb, dev, type, daddr, saddr, len));
    } else {
        return 0;
    }
}

static int comx_rebuild_header(struct sk_buff *skb) 
{
    struct net_device *dev = skb->dev;
    struct comx_channel *ch = dev->priv;

    if (ch->LINE_rebuild_header) {
        return(ch->LINE_rebuild_header(skb));
    } else {
        return 0;
    }
}

int comx_rx(struct net_device *dev, struct sk_buff *skb)
{
    struct comx_channel *ch = dev->priv;

    if (ch->debug_flags & DEBUG_COMX_RX) {
        comx_debug_skb(dev, skb, "comx_rx skb");
    }
    if (skb) {
        netif_rx(skb);
        dev->last_rx = jiffies;
    }
    return 0;
}

static struct net_device_stats *comx_stats(struct net_device *dev)
{
    struct comx_channel *ch = (struct comx_channel *)dev->priv;

    return ch->current_stats;
}

void comx_lineup_func(unsigned long d)
{
    struct net_device *dev = (struct net_device *)d;
    struct comx_channel *ch = dev->priv;

    del_timer(&ch->lineup_timer);
    clear_bit(0, &ch->lineup_pending);

    if (ch->LINE_status) {
        ch->LINE_status(dev, ch->line_status |= LINE_UP);
    }
}

#define LOADAVG(avg, off) (int) \
    ((ch->avg_bytes[(ch->loadavg_counter - 1 + ch->loadavg_size * 2) \
    % ch->loadavg_size + off] -  ch->avg_bytes[(ch->loadavg_counter - 1 \
        - ch->loadavg[avg] / ch->loadavg[0] + ch->loadavg_size * 2) \
        % ch->loadavg_size + off]) / ch->loadavg[avg] * 8)

static int comx_statistics(struct net_device *dev, char *page)
{
    struct comx_channel *ch = dev->priv;
    int len = 0;
    int tmp;
    int i = 0;
    char tmpstr[20];
    int tmpstrlen = 0;

    len += sprintf(page + len, "Interface administrative status is %s, "
        "modem status is %s, protocol is %s\n", 
        dev->flags & IFF_UP ? "UP" : "DOWN",
        ch->line_status & LINE_UP ? "UP" : "DOWN",
        ch->line_status & PROTO_LOOP ? "LOOP" : 
        ch->line_status & PROTO_UP ? "UP" : "DOWN");
    len += sprintf(page + len, "Modem status changes: %lu, Transmitter status "
        "is %s, tbusy: %d\n", ch->current_stats->tx_carrier_errors, ch->HW_txe ? 
        ch->HW_txe(dev) ? "IDLE" : "BUSY" : "NOT READY", netif_running(dev));
    len += sprintf(page + len, "Interface load (input): %d / %d / %d bits/s (",
        LOADAVG(0,0), LOADAVG(1, 0), LOADAVG(2, 0));
    tmpstr[0] = 0;
    for (i=0; i != 3; i++) {
        char tf;

        tf = ch->loadavg[i] % 60 == 0 && 
            ch->loadavg[i] / 60 > 0 ? 'm' : 's';
        tmpstrlen += sprintf(tmpstr + tmpstrlen, "%d%c%s", 
            ch->loadavg[i] / (tf == 'm' ? 60 : 1), tf, 
            i == 2 ? ")\n" : "/");
    }
    len += sprintf(page + len, 
        "%s              (output): %d / %d / %d bits/s (%s", tmpstr, 
        LOADAVG(0,ch->loadavg_size), LOADAVG(1, ch->loadavg_size), 
        LOADAVG(2, ch->loadavg_size), tmpstr);

    len += sprintf(page + len, "Debug flags: ");
    tmp = len; i = 0;
    while (comx_debugflags[i].name) {
        if (ch->debug_flags & comx_debugflags[i].value) 
            len += sprintf(page + len, "%s ", 
                comx_debugflags[i].name);
        i++;
    }
    len += sprintf(page + len, "%s\n", tmp == len ? "none" : "");

    len += sprintf(page + len, "RX errors: len: %lu, overrun: %lu, crc: %lu, "
        "aborts: %lu\n           buffer overrun: %lu, pbuffer overrun: %lu\n"
        "TX errors: underrun: %lu\n",
        ch->current_stats->rx_length_errors, ch->current_stats->rx_over_errors, 
        ch->current_stats->rx_crc_errors, ch->current_stats->rx_frame_errors, 
        ch->current_stats->rx_missed_errors, ch->current_stats->rx_fifo_errors,
        ch->current_stats->tx_fifo_errors);

    if (ch->LINE_statistics && (ch->init_status & LINE_OPEN)) {
        len += ch->LINE_statistics(dev, page + len);
    } else {
        len += sprintf(page+len, "Line status: driver not initialized\n");
    }
    if (ch->HW_statistics && (ch->init_status & HW_OPEN)) {
        len += ch->HW_statistics(dev, page + len);
    } else {
        len += sprintf(page+len, "Board status: driver not initialized\n");
    }

    return len;
}

static int comx_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
    struct comx_channel *ch = dev->priv;

    if (ch->LINE_ioctl) {
        return(ch->LINE_ioctl(dev, ifr, cmd));
    }
    return -EINVAL;
}

static void comx_reset_dev(struct net_device *dev)
{
    dev->open = comx_open;
    dev->stop = comx_close;
    dev->hard_start_xmit = comx_xmit;
    dev->hard_header = comx_header;
    dev->rebuild_header = comx_rebuild_header;
    dev->get_stats = comx_stats;
    dev->do_ioctl = comx_ioctl;
    dev->change_mtu = NULL;
    dev->tx_queue_len = 20;
    dev->flags = IFF_NOARP;
}

static int comx_init_dev(struct net_device *dev)
{
    struct comx_channel *ch;

    if ((ch = kmalloc(sizeof(struct comx_channel), GFP_KERNEL)) == NULL) {
        return -ENOMEM;
    }
    memset(ch, 0, sizeof(struct comx_channel));

    ch->loadavg[0] = 5;
    ch->loadavg[1] = 300;
    ch->loadavg[2] = 900;
    ch->loadavg_size = ch->loadavg[2] / ch->loadavg[0] + 1; 
    if ((ch->avg_bytes = kmalloc(ch->loadavg_size * 
        sizeof(unsigned long) * 2, GFP_KERNEL)) == NULL) {
        kfree(ch);
        return -ENOMEM;
    }

    memset(ch->avg_bytes, 0, ch->loadavg_size * sizeof(unsigned long) * 2);
    ch->loadavg_counter = 0;
    ch->loadavg_timer.function = comx_loadavg_timerfun;
    ch->loadavg_timer.data = (unsigned long)dev;
    ch->loadavg_timer.expires = jiffies + HZ * ch->loadavg[0];
    add_timer(&ch->loadavg_timer);

    dev->priv = (void *)ch;
    ch->dev = dev;
    ch->line_status &= ~LINE_UP;

    ch->current_stats = &ch->stats;

    comx_reset_dev(dev);
    return 0;
}

static int comx_read_proc(char *page, char **start, off_t off, int count, 
    int *eof, void *data)
{
    struct proc_dir_entry *file = (struct proc_dir_entry *)data;
    struct net_device *dev = file->parent->data;
    struct comx_channel *ch=(struct comx_channel *)dev->priv;
    int len = 0;

    if (strcmp(file->name, FILENAME_STATUS) == 0) {
        len = comx_statistics(dev, page);
    } else if (strcmp(file->name, FILENAME_HARDWARE) == 0) {
        len = sprintf(page, "%s\n", ch->hardware ? 
            ch->hardware->name : HWNAME_NONE);
    } else if (strcmp(file->name, FILENAME_PROTOCOL) == 0) {
        len = sprintf(page, "%s\n", ch->protocol ? 
            ch->protocol->name : PROTONAME_NONE);
    } else if (strcmp(file->name, FILENAME_LINEUPDELAY) == 0) {
        len = sprintf(page, "%01d\n", ch->lineup_delay);
    }

    if (off >= len) {
        *eof = 1;
        return 0;
    }

    *start = page + off;
    if (count >= len - off) {
        *eof = 1;
    }
    return min_t(int, count, len - off);
}


static int comx_root_read_proc(char *page, char **start, off_t off, int count, 
    int *eof, void *data)
{
    struct proc_dir_entry *file = (struct proc_dir_entry *)data;
    struct comx_hardware *hw;
    struct comx_protocol *line;

    int len = 0;

    if (strcmp(file->name, FILENAME_HARDWARELIST) == 0) {
        for(hw=comx_channels;hw;hw=hw->next) 
            len+=sprintf(page+len, "%s\n", hw->name);
    } else if (strcmp(file->name, FILENAME_PROTOCOLLIST) == 0) {
        for(line=comx_lines;line;line=line->next)
            len+=sprintf(page+len, "%s\n", line->name);
    }

    if (off >= len) {
        *eof = 1;
        return 0;
    }

    *start = page + off;
    if (count >= len - off) {
        *eof = 1;
    }
    return min_t(int, count, len - off);
}



static int comx_write_proc(struct file *file, const char *buffer, u_long count,
    void *data)
{
    struct proc_dir_entry *entry = (struct proc_dir_entry *)data;
    struct net_device *dev = (struct net_device *)entry->parent->data;
    struct comx_channel *ch=(struct comx_channel *)dev->priv;
    char *page;
    struct comx_hardware *hw = comx_channels;
    struct comx_protocol *line = comx_lines;
    char str[30];
    int ret=0;

    if (count > PAGE_SIZE) {
        printk(KERN_ERR "count is %lu > %d!!!\n", count, (int)PAGE_SIZE);
        return -ENOSPC;
    }

    if (!(page = (char *)__get_free_page(GFP_KERNEL))) return -ENOMEM;

    if(copy_from_user(page, buffer, count))
    {
        count = -EFAULT;
        goto out;
    }

    if (page[count-1] == '\n')
        page[count-1] = '\0';
    else if (count < PAGE_SIZE)
        page[count] = '\0';
    else if (page[count]) {
        count = -EINVAL;
        goto out;
    }

    if (strcmp(entry->name, FILENAME_DEBUG) == 0) {
        int i;
        int ret = 0;

        if ((i = simple_strtoul(page, NULL, 10)) != 0) {
            unsigned long flags;

            save_flags(flags); cli();
            if (ch->debug_area) kfree(ch->debug_area);
            if ((ch->debug_area = kmalloc(ch->debug_size = i, 
                GFP_KERNEL)) == NULL) {
                ret = -ENOMEM;
            }
            ch->debug_start = ch->debug_end = 0;
            restore_flags(flags);
            free_page((unsigned long)page);
            return ret ? ret : count;
        }
        
        if (*page != '+' && *page != '-') {
            free_page((unsigned long)page);
            return -EINVAL;
        }
        while (comx_debugflags[i].value && 
            strncmp(comx_debugflags[i].name, page + 1, 
            strlen(comx_debugflags[i].name))) {
            i++;
        }
    
        if (comx_debugflags[i].value == 0) {
            printk(KERN_ERR "Invalid debug option\n");
            free_page((unsigned long)page);
            return -EINVAL;
        }
        if (*page == '+') {
            ch->debug_flags |= comx_debugflags[i].value;
        } else {
            ch->debug_flags &= ~comx_debugflags[i].value;
        }
    } else if (strcmp(entry->name, FILENAME_HARDWARE) == 0) {
        if(strlen(page)>10) {
            free_page((unsigned long)page);
            return -EINVAL;
        }
        while (hw) { 
            if (strcmp(hw->name, page) == 0) {
                break;
            } else {
                hw = hw->next;
            }
        }
#ifdef CONFIG_KMOD
        if(!hw && comx_strcasecmp(HWNAME_NONE,page) != 0){
            sprintf(str,"comx-hw-%s",page);
            request_module(str);
        }        
        hw=comx_channels;
        while (hw) {
            if (comx_strcasecmp(hw->name, page) == 0) {
                break;
            } else {
                hw = hw->next;
            }
        }
#endif

        if (comx_strcasecmp(HWNAME_NONE, page) != 0 && !hw)  {
            free_page((unsigned long)page);
            return -ENODEV;
        }
        if (ch->init_status & HW_OPEN) {
            free_page((unsigned long)page);
            return -EBUSY;
        }
        if (ch->hardware && ch->hardware->hw_exit && 
           (ret=ch->hardware->hw_exit(dev))) {
            free_page((unsigned long)page);
            return ret;
        }
        ch->hardware = hw;
        entry->size = strlen(page) + 1;
        if (hw && hw->hw_init) hw->hw_init(dev);
    } else if (strcmp(entry->name, FILENAME_PROTOCOL) == 0) {
        if(strlen(page)>10) {
            free_page((unsigned long)page);
            return -EINVAL;
        }
        while (line) {
            if (comx_strcasecmp(line->name, page) == 0) {
                break;
            } else {
                line = line->next;
            }
        }
#ifdef CONFIG_KMOD
        if(!line && comx_strcasecmp(PROTONAME_NONE, page) != 0) {
            sprintf(str,"comx-proto-%s",page);
            request_module(str);
        }        
        line=comx_lines;
        while (line) {
            if (comx_strcasecmp(line->name, page) == 0) {
                break;
            } else {
                line = line->next;
            }
        }
#endif
        
        if (comx_strcasecmp(PROTONAME_NONE, page) != 0 && !line) {
            free_page((unsigned long)page);
            return -ENODEV;
        }
        
        if (ch->init_status & LINE_OPEN) {
            free_page((unsigned long)page);
            return -EBUSY;
        }
        
        if (ch->protocol && ch->protocol->line_exit && 
            (ret=ch->protocol->line_exit(dev))) {
            free_page((unsigned long)page);
            return ret;
        }
        ch->protocol = line;
        entry->size = strlen(page) + 1;
        comx_reset_dev(dev);
        if (line && line->line_init) line->line_init(dev);
    } else if (strcmp(entry->name, FILENAME_LINEUPDELAY) == 0) {
        int i;

        if ((i = simple_strtoul(page, NULL, 10)) != 0) {
            if (i >=0 && i < 10) { 
                ch->lineup_delay = i; 
            } else {
                printk(KERN_ERR "comx: invalid lineup_delay value\n");
            }
        }
    }
out:
    free_page((unsigned long)page);
    return count;
}

static int comx_mkdir(struct inode *dir, struct dentry *dentry, int mode)
{
    struct proc_dir_entry *new_dir, *debug_file;
    struct net_device *dev;
    struct comx_channel *ch;
    int ret = -EIO;

    if ((dev = kmalloc(sizeof(struct net_device), GFP_KERNEL)) == NULL) {
        return -ENOMEM;
    }
    memset(dev, 0, sizeof(struct net_device));

    if ((new_dir = create_proc_entry(dentry->d_name.name, mode | S_IFDIR, 
        comx_root_dir)) == NULL) {
        goto cleanup_dev;
    }

    new_dir->nlink = 2;
    new_dir->data = NULL; // ide jon majd a struct dev

    /* Ezek kellenek */
    if (!create_comx_proc_entry(FILENAME_HARDWARE, 0644, 
        strlen(HWNAME_NONE) + 1, new_dir)) {
        goto cleanup_new_dir;
    }
    if (!create_comx_proc_entry(FILENAME_PROTOCOL, 0644, 
        strlen(PROTONAME_NONE) + 1, new_dir)) {
        goto cleanup_filename_hardware;
    }
    if (!create_comx_proc_entry(FILENAME_STATUS, 0444, 0, new_dir)) {
        goto cleanup_filename_protocol;
    }
    if (!create_comx_proc_entry(FILENAME_LINEUPDELAY, 0644, 2, new_dir)) {
        goto cleanup_filename_status;
    }

    if ((debug_file = create_proc_entry(FILENAME_DEBUG, 
        S_IFREG | 0644, new_dir)) == NULL) {
        goto cleanup_filename_lineupdelay;
    }
    debug_file->data = (void *)debug_file; 
    debug_file->read_proc = NULL; // see below
    debug_file->write_proc = &comx_write_proc;
    debug_file->nlink = 1;

    strcpy(dev->name, (char *)new_dir->name);
    dev->init = comx_init_dev;

    if (register_netdevice(dev)) {
        goto cleanup_filename_debug;
    }
    ch=dev->priv;
    if((ch->if_ptr = (void *)kmalloc(sizeof(struct ppp_device), 
                 GFP_KERNEL)) == NULL) {
        goto cleanup_register;
    }
    memset(ch->if_ptr, 0, sizeof(struct ppp_device));
    ch->debug_file = debug_file; 
    ch->procdir = new_dir;
    new_dir->data = dev;

    ch->debug_start = ch->debug_end = 0;
    if ((ch->debug_area = kmalloc(ch->debug_size = DEFAULT_DEBUG_SIZE, 
        GFP_KERNEL)) == NULL) {
        ret = -ENOMEM;
        goto cleanup_if_ptr;
    }

    ch->lineup_delay = DEFAULT_LINEUP_DELAY;

    MOD_INC_USE_COUNT;
    return 0;
cleanup_if_ptr:
    kfree(ch->if_ptr);
cleanup_register:
    unregister_netdevice(dev);
cleanup_filename_debug:
    remove_proc_entry(FILENAME_DEBUG, new_dir);
cleanup_filename_lineupdelay:
    remove_proc_entry(FILENAME_LINEUPDELAY, new_dir);
cleanup_filename_status:
    remove_proc_entry(FILENAME_STATUS, new_dir);
cleanup_filename_protocol:
    remove_proc_entry(FILENAME_PROTOCOL, new_dir);
cleanup_filename_hardware:
    remove_proc_entry(FILENAME_HARDWARE, new_dir);
cleanup_new_dir:
    remove_proc_entry(dentry->d_name.name, comx_root_dir);
cleanup_dev:
    kfree(dev);
    return ret;
}

static int comx_rmdir(struct inode *dir, struct dentry *dentry)
{
    struct proc_dir_entry *entry = dentry->d_inode->u.generic_ip;
    struct net_device *dev = entry->data;
    struct comx_channel *ch = dev->priv;
    int ret;

    if (dev->flags & IFF_UP) {
        printk(KERN_ERR "%s: down interface before removing it\n", dev->name);
        return -EBUSY;
    }

    if (ch->protocol && ch->protocol->line_exit && 
        (ret=ch->protocol->line_exit(dev))) {
        return ret;
    }
    if (ch->hardware && ch->hardware->hw_exit && 
       (ret=ch->hardware->hw_exit(dev))) { 
        if(ch->protocol && ch->protocol->line_init) {
            ch->protocol->line_init(dev);
        }
        return ret;
    }
    ch->protocol = NULL;
    ch->hardware = NULL;

    del_timer(&ch->loadavg_timer);
    kfree(ch->avg_bytes);

    unregister_netdev(dev);
    if (ch->debug_area) {
        kfree(ch->debug_area);
    }
    if (dev->priv) {
        kfree(dev->priv);
    }
    kfree(dev);

    remove_proc_entry(FILENAME_DEBUG, entry);
    remove_proc_entry(FILENAME_LINEUPDELAY, entry);
    remove_proc_entry(FILENAME_STATUS, entry);
    remove_proc_entry(FILENAME_HARDWARE, entry);
    remove_proc_entry(FILENAME_PROTOCOL, entry);
    remove_proc_entry(dentry->d_name.name, comx_root_dir);

    MOD_DEC_USE_COUNT;
    return 0;
}

static struct dentry *comx_lookup(struct inode *dir, struct dentry *dentry)
{
    struct proc_dir_entry *de;
    struct inode *inode = NULL;

    if ((de = (struct proc_dir_entry *) dir->u.generic_ip) != NULL) {
        for (de = de->subdir ; de ; de = de->next) {
            if ((de && de->low_ino) && 
                (de->namelen == dentry->d_name.len) &&
                (memcmp(dentry->d_name.name, de->name, 
                de->namelen) == 0))    {
                 if ((inode = proc_get_inode(dir->i_sb, 
                     de->low_ino, de)) == NULL) { 
                     printk(KERN_ERR "COMX: lookup error\n"); 
                     return ERR_PTR(-EINVAL); 
                 }
                break;
            }
        }
    }
    dentry->d_op = &comx_dentry_operations;
    d_add(dentry, inode);
    return NULL;
}

int comx_strcasecmp(const char *cs, const char *ct)
{
    register signed char __res;

    while (1) {
        if ((__res = toupper(*cs) - toupper(*ct++)) != 0 || !*cs++) {
            break;
        }
    }
    return __res;
}

static int comx_delete_dentry(struct dentry *dentry)
{
    return 1;
}

static struct proc_dir_entry *create_comx_proc_entry(char *name, int mode,
    int size, struct proc_dir_entry *dir)
{
    struct proc_dir_entry *new_file;

    if ((new_file = create_proc_entry(name, S_IFREG | mode, dir)) != NULL) {
        new_file->data = (void *)new_file;
        new_file->read_proc = &comx_read_proc;
        new_file->write_proc = &comx_write_proc;
        new_file->size = size;
        new_file->nlink = 1;
    }
    return(new_file);
}

int comx_register_hardware(struct comx_hardware *comx_hw)
{
    struct comx_hardware *hw = comx_channels;

    if (!hw) {
        comx_channels = comx_hw;
    } else {
        while (hw->next != NULL && strcmp(comx_hw->name, hw->name) != 0) {
            hw = hw->next;
        }
        if (strcmp(comx_hw->name, hw->name) == 0) {
            return -1;
        }
        hw->next = comx_hw;
    }

    printk(KERN_INFO "COMX: driver for hardware type %s, version %s\n", comx_hw->name, comx_hw->version);
    return 0;
}

int comx_unregister_hardware(char *name)
{
    struct comx_hardware *hw = comx_channels;

    if (!hw) {
        return -1;
    }

    if (strcmp(hw->name, name) == 0) {
        comx_channels = comx_channels->next;
        return 0;
    }

    while (hw->next != NULL && strcmp(hw->next->name,name) != 0) {
        hw = hw->next;
    }

    if (hw->next != NULL && strcmp(hw->next->name, name) == 0) {
        hw->next = hw->next->next;
        return 0;
    }
    return -1;
}

int comx_register_protocol(struct comx_protocol *comx_line)
{
    struct comx_protocol *pr = comx_lines;

    if (!pr) {
        comx_lines = comx_line;
    } else {
        while (pr->next != NULL && strcmp(comx_line->name, pr->name) !=0) {
            pr = pr->next;
        }
        if (strcmp(comx_line->name, pr->name) == 0) {
            return -1;
        }
        pr->next = comx_line;
    }

    printk(KERN_INFO "COMX: driver for protocol type %s, version %s\n", comx_line->name, comx_line->version);
    return 0;
}

int comx_unregister_protocol(char *name)
{
    struct comx_protocol *pr = comx_lines;

    if (!pr) {
        return -1;
    }

    if (strcmp(pr->name, name) == 0) {
        comx_lines = comx_lines->next;
        return 0;
    }

    while (pr->next != NULL && strcmp(pr->next->name,name) != 0) {
        pr = pr->next;
    }

    if (pr->next != NULL && strcmp(pr->next->name, name) == 0) {
        pr->next = pr->next->next;
        return 0;
    }
    return -1;
}

#ifdef MODULE
#define comx_init init_module
#endif

int __init comx_init(void)
{
    struct proc_dir_entry *new_file;

    comx_root_dir = create_proc_entry("comx", 
        S_IFDIR | S_IWUSR | S_IRUGO | S_IXUGO, &proc_root);
    if (!comx_root_dir)
        return -ENOMEM;
    comx_root_dir->proc_iops = &comx_root_inode_ops;

    if ((new_file = create_proc_entry(FILENAME_HARDWARELIST, 
       S_IFREG | 0444, comx_root_dir)) == NULL) {
        return -ENOMEM;
    }
    
    new_file->data = new_file;
    new_file->read_proc = &comx_root_read_proc;
    new_file->write_proc = NULL;
    new_file->nlink = 1;

    if ((new_file = create_proc_entry(FILENAME_PROTOCOLLIST, 
       S_IFREG | 0444, comx_root_dir)) == NULL) {
        return -ENOMEM;
    }
    
    new_file->data = new_file;
    new_file->read_proc = &comx_root_read_proc;
    new_file->write_proc = NULL;
    new_file->nlink = 1;


    printk(KERN_INFO "COMX: driver version %s (C) 1995-1999 ITConsult-Pro Co. <info@itc.hu>\n", 
        VERSION);

#ifndef MODULE
#ifdef CONFIG_COMX_HW_COMX
    comx_hw_comx_init();
#endif
#ifdef CONFIG_COMX_HW_LOCOMX
    comx_hw_locomx_init();
#endif
#ifdef CONFIG_COMX_HW_MIXCOM
    comx_hw_mixcom_init();
#endif
#ifdef CONFIG_COMX_PROTO_HDLC
    comx_proto_hdlc_init();
#endif
#ifdef CONFIG_COMX_PROTO_PPP
    comx_proto_ppp_init();
#endif
#ifdef CONFIG_COMX_PROTO_LAPB
    comx_proto_lapb_init();
#endif
#ifdef CONFIG_COMX_PROTO_FR
    comx_proto_fr_init();
#endif
#endif

    return 0;
}

#ifdef MODULE
void cleanup_module(void)
{
    remove_proc_entry(FILENAME_HARDWARELIST, comx_root_dir);
    remove_proc_entry(FILENAME_PROTOCOLLIST, comx_root_dir);
    remove_proc_entry(comx_root_dir->name, &proc_root);
}
#endif

EXPORT_SYMBOL(comx_register_hardware);
EXPORT_SYMBOL(comx_unregister_hardware);
EXPORT_SYMBOL(comx_register_protocol);
EXPORT_SYMBOL(comx_unregister_protocol);
EXPORT_SYMBOL(comx_debug_skb);
EXPORT_SYMBOL(comx_debug_bytes);
EXPORT_SYMBOL(comx_debug);
EXPORT_SYMBOL(comx_lineup_func);
EXPORT_SYMBOL(comx_status);
EXPORT_SYMBOL(comx_rx);
EXPORT_SYMBOL(comx_strcasecmp);
EXPORT_SYMBOL(comx_root_dir);

:: Command execute ::

Enter:
 
Select:
 

:: Search ::
  - regexp 

:: Upload ::
 
[ Read-Only ]

:: Make Dir ::
 
[ Read-Only ]
:: Make File ::
 
[ Read-Only ]

:: Go Dir ::
 
:: Go File ::
 

--[ c99shell v. 1.0 pre-release build #13 powered by Captain Crunch Security Team | http://ccteam.ru | Generation time: 0.0305 ]--