static int rtmac_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
	struct rtmac_config cfg;
	struct rtnet_device *rtdev;

	if( !suser() )
		return -EPERM;

	if( copy_from_user(&cfg, (void*)arg, sizeof(struct rtmac_config)) )
		return -EFAULT;

	rtdev = rtdev_get_by_name(cfg.if_name);

	if( !rtdev ) {
		rt_printk("RTmac: invalid interface %s\n", cfg.if_name);
		return -ENODEV;
	}

	if( !(rtdev->rtmac && rtdev->rtmac->ioctl_ops) ) {
		return -ENOTTY;
	}

	switch( cmd ) {
	case RTMAC_IOC_CLIENT:
		return rtmac_ioctl_client(rtdev);
		break;
	case RTMAC_IOC_MASTER:
		return rtmac_ioctl_master(rtdev, cfg.cycle, cfg.mtu);
		break;
	case RTMAC_IOC_UP:
		return rtmac_ioctl_up(rtdev);
		break;
	case RTMAC_IOC_DOWN:
		return rtmac_ioctl_down(rtdev);
		break;
	case RTMAC_IOC_ADD:
		return rtmac_ioctl_add(rtdev, cfg.ip_addr);
		break;
	case RTMAC_IOC_REMOVE:
		return rtmac_ioctl_remove(rtdev, cfg.ip_addr);
		break;
	case RTMAC_IOC_ADD_NRT:
		return rtmac_ioctl_add_nrt(rtdev, cfg.ip_addr);
		break;
	case RTMAC_IOC_REMOVE_NRT:
		return rtmac_ioctl_remove_nrt(rtdev, cfg.ip_addr);
		break;
	case RTMAC_IOC_CYCLE:
		return rtmac_ioctl_cycle(rtdev, cfg.cycle);
		break;
	case RTMAC_IOC_MTU:
		return rtmac_ioctl_mtu(rtdev, cfg.mtu);
		break;
	case RTMAC_IOC_OFFSET:
		return rtmac_ioctl_offset(rtdev, cfg.ip_addr, cfg.offset);
	default:
		return -ENOTTY;
	}
}
void rtmac_release(void)
{
	rt_printk("RTmac: end realtime medium access control\n");

	tdma_stop(rtdev_get_by_name(dev));

#ifdef CONFIG_PROC_FS
	rtmac_proc_release();
#endif

	rtmac_chrdev_release();
}
Beispiel #3
0
/***
 *  rtdev_alloc_name - allocate a name for the rtnet_device
 *  @rtdev:         the rtnet_device
 *  @name_mask:     a name mask (e.g. "rteth%d" for ethernet)
 *
 *  This function have to be called from the driver probe function.
 */
void rtdev_alloc_name(struct rtnet_device *rtdev, const char *mask)
{
    char buf[IFNAMSIZ];
    int i;
    struct rtnet_device *tmp;

    for (i = 0; i < MAX_RT_DEVICES; i++) {
        snprintf(buf, IFNAMSIZ, mask, i);
        if ((tmp = rtdev_get_by_name(buf)) == NULL) {
            strncpy(rtdev->name, buf, IFNAMSIZ);
            break;
        }
        else
            rtdev_dereference(tmp);
    }
}
int rtmac_init(void)
{
	int ret = 0;

	rt_printk("RTmac: init realtime medium access control\n");

	ret = tdma_start(rtdev_get_by_name(dev));
	if (ret)
		return ret;

#ifdef CONFIG_PROC_FS
	ret = rtmac_proc_register();
	if (ret)
		return ret;
#endif
	ret = rtmac_chrdev_init();
	if (ret)
		return ret;

	return ret;
}
Beispiel #5
0
/***
 *  rt_socket_if_ioctl
 */
int rt_socket_if_ioctl(struct rtdm_dev_context *context, int call_flags,
                       int request, void *arg)
{
    struct rtnet_device     *rtdev;
    struct ifreq            *cur_ifr;
    struct sockaddr_in      *sin;
    int                     i;
    int                     size;
    struct ifconf           *ifc = arg;
    struct ifreq            *ifr = arg;
    int                     ret = 0;


    switch (request) {
        case SIOCGIFCONF:
            size = 0;
            cur_ifr = ifc->ifc_req;

            for (i = 1; i <= MAX_RT_DEVICES; i++) {
                rtdev = rtdev_get_by_index(i);
                if (rtdev != NULL) {
                    if ((rtdev->flags & IFF_RUNNING) == 0) {
                        rtdev_dereference(rtdev);
                        continue;
                    }

                    size += sizeof(struct ifreq);
                    if (size > ifc->ifc_len) {
                        rtdev_dereference(rtdev);
                        size = ifc->ifc_len;
                        break;
                    }

                    strncpy(cur_ifr->ifr_name, rtdev->name,
                            IFNAMSIZ);
                    sin = (struct sockaddr_in *)&cur_ifr->ifr_addr;
                    sin->sin_family      = AF_INET;
                    sin->sin_addr.s_addr = rtdev->local_ip;

                    cur_ifr++;
                    rtdev_dereference(rtdev);
                }
            }

            ifc->ifc_len = size;
            break;

        case SIOCGIFFLAGS:
            rtdev = rtdev_get_by_name(ifr->ifr_name);
            if (rtdev == NULL)
                return -ENODEV;
            else {
                ifr->ifr_flags = rtdev->flags;
                rtdev_dereference(rtdev);
            }
            break;

        default:
            ret = -EOPNOTSUPP;
            break;
    }

    return ret;
}
Beispiel #6
0
int rtwlan_tx(struct rtskb *rtskb, struct rtnet_device *rtnet_dev)
{
    struct rtwlan_device * rtwlan = rtnetdev_priv(rtnet_dev);
    struct ieee80211_hdr_3addr header = {	/* Ensure zero initialized */
        .duration_id = 0,
        .seq_ctl = 0
    };
    u8 dest[ETH_ALEN], src[ETH_ALEN];

    /* Save source and destination addresses */
    memcpy(dest, rtskb->data, ETH_ALEN);
    memcpy(src, rtskb->data + ETH_ALEN, ETH_ALEN);

    /* Generate ieee80211 compatible header */
    memcpy(header.addr3, src, ETH_ALEN);	/* BSSID */
    memcpy(header.addr2, src, ETH_ALEN);	/* SA */
    memcpy(header.addr1, dest, ETH_ALEN);	/* DA */

    /* Frame Control */
    switch(rtwlan->mode) {
        case RTWLAN_MODE_RAW:
            header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
            break;

        case RTWLAN_MODE_ACK:
            header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA);
            break;

        default:
            return -1;
    }

    memcpy(rtskb_push(rtskb, IEEE80211_3ADDR_LEN), &header, IEEE80211_3ADDR_LEN);

    return 0;
}

EXPORT_SYMBOL(rtwlan_tx);


/**
 * rtalloc_wlandev - Allocates and sets up a wlan device
 * @sizeof_priv: size of additional driver-private structure to
 *               be allocated for this wlan device
 *
 * Fill in the fields of the device structure with wlan-generic
 * values. Basically does everything except registering the device.
 *
 * A 32-byte alignment is enforced for the private data area.
 */

struct rtnet_device * rtwlan_alloc_dev(int sizeof_priv)
{
    struct rtnet_device *rtnet_dev;

    RTWLAN_DEBUG("Start.\n");

    rtnet_dev = rt_alloc_etherdev(sizeof(struct rtwlan_device) + sizeof_priv);
    if (!rtnet_dev)
        return NULL;

    rtdev_alloc_name(rtnet_dev, "rtwlan%d");

    return rtnet_dev;
}

EXPORT_SYMBOL(rtwlan_alloc_dev);


int rtwlan_ioctl(struct rtnet_device * rtdev,
                 unsigned int request,
                 unsigned long arg)
{
    struct rtwlan_cmd cmd;
    int ret=0;

    if (copy_from_user(&cmd, (void *)arg, sizeof(cmd)) != 0)
        return -EFAULT;

    switch(request) {
        case IOC_RTWLAN_IFINFO:
            if (cmd.args.info.ifindex > 0)
                rtdev = rtdev_get_by_index(cmd.args.info.ifindex);
            else
                rtdev = rtdev_get_by_name(cmd.head.if_name);
            if (rtdev == NULL)
                return -ENODEV;

            if (down_interruptible(&rtdev->nrt_lock)) {
                rtdev_dereference(rtdev);
                return -ERESTARTSYS;
            }

            if (rtdev->do_ioctl)
                ret = rtdev->do_ioctl(rtdev, request, &cmd);
            else 
                ret = -ENORTWLANDEV;

            memcpy(cmd.head.if_name, rtdev->name, IFNAMSIZ);
            cmd.args.info.ifindex      = rtdev->ifindex;
            cmd.args.info.flags        = rtdev->flags;

            up(&rtdev->nrt_lock);

            rtdev_dereference(rtdev);

            break;

        case IOC_RTWLAN_MODE:
        case IOC_RTWLAN_BITRATE:
        case IOC_RTWLAN_CHANNEL:
        case IOC_RTWLAN_TXPOWER:
        case IOC_RTWLAN_DROPBCAST:
        case IOC_RTWLAN_DROPMCAST:
        case IOC_RTWLAN_REGREAD:
        case IOC_RTWLAN_REGWRITE:
        case IOC_RTWLAN_BBPWRITE:
        case IOC_RTWLAN_BBPREAD:
        case IOC_RTWLAN_BBPSENS:
            if (down_interruptible(&rtdev->nrt_lock))
                return -ERESTARTSYS;

            if (rtdev->do_ioctl)
                ret = rtdev->do_ioctl(rtdev, request, &cmd);
            else
                ret = -ENORTWLANDEV;

            up(&rtdev->nrt_lock);

            break;

        default:
            ret = -ENOTTY;
    }

    if (copy_to_user((void *)arg, &cmd, sizeof(cmd)) != 0)
        return -EFAULT;

    return ret;
}


struct rtnet_ioctls rtnet_wlan_ioctls = {
    service_name: "rtwlan ioctl",
    ioctl_type: RTNET_IOC_TYPE_RTWLAN,
    handler: rtwlan_ioctl
};
Beispiel #7
0
/***
 *  rt_socket_if_ioctl
 */
int rt_socket_if_ioctl(struct rtdm_dev_context *sockctx,
                       rtdm_user_info_t *user_info, int request, void *arg)
{
    struct rtnet_device *rtdev;
    struct ifreq        *ifr = arg;
    struct sockaddr_in  *sin;
    int                 ret = 0;


    if (request == SIOCGIFCONF) {
        struct ifconf       *ifc = arg;
        struct ifreq        *cur_ifr = ifc->ifc_req;
        int                 size = 0;
        int                 i;

        for (i = 1; i <= MAX_RT_DEVICES; i++) {
            rtdev = rtdev_get_by_index(i);
            if (rtdev != NULL) {
                if ((rtdev->flags & IFF_RUNNING) == 0) {
                    rtdev_dereference(rtdev);
                    continue;
                }

                size += sizeof(struct ifreq);
                if (size > ifc->ifc_len) {
                    rtdev_dereference(rtdev);
                    size = ifc->ifc_len;
                    break;
                }

                strncpy(cur_ifr->ifr_name, rtdev->name,
                        IFNAMSIZ);
                sin = (struct sockaddr_in *)&cur_ifr->ifr_addr;
                sin->sin_family      = AF_INET;
                sin->sin_addr.s_addr = rtdev->local_ip;

                cur_ifr++;
                rtdev_dereference(rtdev);
            }
        }

        ifc->ifc_len = size;
        return 0;
    }

    rtdev = rtdev_get_by_name(ifr->ifr_name);
    if (rtdev == NULL)
        return -ENODEV;

    switch (request) {
        case SIOCGIFINDEX:
            ifr->ifr_ifindex = rtdev->ifindex;
            break;

        case SIOCGIFFLAGS:
            ifr->ifr_flags = rtdev->flags;
            break;

        case SIOCGIFHWADDR:
            memcpy(ifr->ifr_hwaddr.sa_data, rtdev->dev_addr, rtdev->addr_len);
            ifr->ifr_hwaddr.sa_family = rtdev->type;
            break;

        case SIOCGIFADDR:
            sin = (struct sockaddr_in *)&ifr->ifr_addr;
            sin->sin_family      = AF_INET;
            sin->sin_addr.s_addr = rtdev->local_ip;
            break;

        case SIOCETHTOOL:
            if (rtdev->do_ioctl != NULL)
                ret = rtdev->do_ioctl(rtdev, request, arg);
            else
                ret = -EOPNOTSUPP;
            break;

        default:
            ret = -EOPNOTSUPP;
            break;
    }

    rtdev_dereference(rtdev);
    return ret;
}
Beispiel #8
0
/**
 * rtnet_ioctl -
 * @inode:
 * @file:
 * @cmd:
 * @arg:
 */
static int rtnet_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
	struct rtnet_config cfg;
	struct rtnet_device *rtdev;
	int ret;

	if (!suser())return -EPERM;

	ret = copy_from_user(&cfg, (void *)arg, sizeof(cfg));
	if (ret) return -EFAULT;

	rtdev = rtdev_get_by_name(cfg.if_name);
	if ( !rtdev ) {
		rt_printk("RTnet: invalid interface %s\n", cfg.if_name);
		return -ENODEV;
	}
	switch(cmd){
	case IOC_RT_IFUP:
		ret = rtdev_open(rtdev);				// = 0, if dev already up
		/*
		 * if device already up and ip changes, delete routing table and add new route
		 * if the dev changes state from close->open also add new route
		 *
		 * pretty ugly, isn't it ;)
		 *
		 */
		if( ret == 0 ) {
			if( rtdev->local_addr != cfg.ip_addr ) {
				rt_ip_route_del(rtdev);

				rtdev->local_addr = cfg.ip_addr;
				rt_ip_route_add(rtdev, cfg.ip_netaddr, cfg.ip_mask);
				rt_arp_table_add(cfg.ip_addr, rtdev->dev_addr);
				rt_ip_route_add_specific(rtdev, cfg.ip_broadcast, rtdev->broadcast);
			}
		} else {
			rtdev->local_addr = cfg.ip_addr;
			rt_ip_route_add(rtdev, cfg.ip_netaddr, cfg.ip_mask);
			rt_arp_table_add(cfg.ip_addr, rtdev->dev_addr);
			rt_ip_route_add_specific(rtdev, cfg.ip_broadcast, rtdev->broadcast);

		}
		return 0;
		
	case IOC_RT_IFDOWN:
		/*
		 * if rtmac is active on dev, don't shut it down....
		 *
		 * FIXME: if mac exists shut mac down, then device...
		 */
		if( rtdev->rtmac ) {
			rt_printk("rtnet: rtmac is active on dev %s, cannot shut down\n", rtdev->name);
			return -ENOTTY;
		}
		rt_ip_route_del(rtdev);
		rtdev_close(rtdev);
		return 0;
		
	case IOC_RT_ROUTE_SOLICIT:
		rt_arp_solicit(rtdev,cfg.ip_addr);
		return 0;

	case IOC_RT_ROUTE_DELETE:
		// Billa: delete an ARP & ROUTE element in the lists
		rt_arp_table_del(cfg.ip_addr);
		rt_ip_route_del_specific(rtdev,cfg.ip_addr);
		return 0;

	default:
		return -ENOTTY;
	}
}