static void rtcfg_conn_check_cfg_timeout(struct rtcfg_connection *conn) { struct rtcfg_device *rtcfg_dev; if (!conn->cfg_timeout) return; if (rtdm_clock_read() >= conn->last_frame + conn->cfg_timeout) { rtcfg_dev = &device[conn->ifindex]; rtcfg_dev->stations_found--; if (conn->state == RTCFG_CONN_STAGE_2) rtcfg_dev->spec.srv.clients_configured--; rtcfg_next_conn_state(conn, RTCFG_CONN_SEARCHING); conn->cfg_offs = 0; conn->flags = 0; #ifdef CONFIG_RTNET_RTIPV4 if (conn->addr_type == RTCFG_ADDR_IP) { struct rtnet_device *rtdev; /* MAC address yet unknown -> use broadcast address */ rtdev = rtdev_get_by_index(conn->ifindex); if (rtdev == NULL) return; memcpy(conn->mac_addr, rtdev->broadcast, MAX_ADDR_LEN); rtdev_dereference(rtdev); } #endif /* CONFIG_RTNET_RTIPV4 */ } }
int rtcfg_send_ready(int ifindex) { struct rtnet_device *rtdev; struct rtskb *rtskb; unsigned int rtskb_size; struct rtcfg_frm_ready *ready_frm; rtdev = rtdev_get_by_index(ifindex); if (rtdev == NULL) return -ENODEV; rtskb_size = rtdev->hard_header_len + sizeof(struct rtcfg_frm_ready); rtskb = alloc_rtskb(rtskb_size, &rtcfg_pool); if (rtskb == NULL) { rtdev_dereference(rtdev); return -ENOBUFS; } rtskb_reserve(rtskb, rtdev->hard_header_len); ready_frm = (struct rtcfg_frm_ready *) rtskb_put(rtskb, sizeof(struct rtcfg_frm_ready)); ready_frm->head.id = RTCFG_ID_READY; ready_frm->head.version = 0; return rtcfg_send_frame(rtskb, rtdev, eth_broadcast); }
/*** * rt_packet_getsockname */ int rt_packet_getsockname(struct rtsocket *s, struct sockaddr *addr, socklen_t *addrlen) { struct sockaddr_ll *sll = (struct sockaddr_ll*)addr; struct rtnet_device *rtdev; if (*addrlen < sizeof(struct sockaddr_ll)) return -EINVAL; sll->sll_family = AF_PACKET; sll->sll_ifindex = s->prot.packet.ifindex; sll->sll_protocol = s->protocol; rtdev = rtdev_get_by_index(s->prot.packet.ifindex); if (rtdev != NULL) { sll->sll_hatype = rtdev->type; sll->sll_halen = rtdev->addr_len; memcpy(sll->sll_addr, rtdev->dev_addr, rtdev->addr_len); rtdev_dereference(rtdev); } else { sll->sll_hatype = 0; sll->sll_halen = 0; } *addrlen = sizeof(struct sockaddr_ll); return 0; }
int rtcfg_send_ack(int ifindex) { struct rtnet_device *rtdev; struct rtskb *rtskb; unsigned int rtskb_size; struct rtcfg_frm_ack_cfg *ack_frm; rtdev = rtdev_get_by_index(ifindex); if (rtdev == NULL) return -ENODEV; rtskb_size = rtdev->hard_header_len + sizeof(struct rtcfg_frm_ack_cfg); rtskb = alloc_rtskb(rtskb_size, &rtcfg_pool); if (rtskb == NULL) { rtdev_dereference(rtdev); return -ENOBUFS; } rtskb_reserve(rtskb, rtdev->hard_header_len); ack_frm = (struct rtcfg_frm_ack_cfg *) rtskb_put(rtskb, sizeof(struct rtcfg_frm_ack_cfg)); ack_frm->head.id = RTCFG_ID_ACK_CFG; ack_frm->head.version = 0; ack_frm->ack_len = htonl(device[ifindex].cfg_offs); return rtcfg_send_frame(rtskb, rtdev, device[ifindex].srv_mac_addr); }
int rtcfg_send_stage_1(struct rtcfg_connection *conn) { struct rtnet_device *rtdev; struct rtskb *rtskb; unsigned int rtskb_size; struct rtcfg_frm_stage_1_cfg *stage_1_frm; rtdev = rtdev_get_by_index(conn->ifindex); if (rtdev == NULL) return -ENODEV; rtskb_size = rtdev->hard_header_len + sizeof(struct rtcfg_frm_stage_1_cfg) + conn->stage1_size + #ifdef CONFIG_RTNET_RTIPV4 (((conn->addr_type & RTCFG_ADDR_MASK) == RTCFG_ADDR_IP) ? 2*RTCFG_ADDRSIZE_IP : 0); #else /* !CONFIG_RTNET_RTIPV4 */ 0; #endif /* CONFIG_RTNET_RTIPV4 */ rtskb = alloc_rtskb(rtskb_size, &rtcfg_pool); if (rtskb == NULL) { rtdev_dereference(rtdev); return -ENOBUFS; } rtskb_reserve(rtskb, rtdev->hard_header_len); stage_1_frm = (struct rtcfg_frm_stage_1_cfg *) rtskb_put(rtskb, sizeof(struct rtcfg_frm_stage_1_cfg)); stage_1_frm->head.id = RTCFG_ID_STAGE_1_CFG; stage_1_frm->head.version = 0; stage_1_frm->addr_type = conn->addr_type & RTCFG_ADDR_MASK; #ifdef CONFIG_RTNET_RTIPV4 if (stage_1_frm->addr_type == RTCFG_ADDR_IP) { rtskb_put(rtskb, 2*RTCFG_ADDRSIZE_IP); memcpy(stage_1_frm->client_addr, &(conn->addr.ip_addr), 4); stage_1_frm = (struct rtcfg_frm_stage_1_cfg *) (((u8 *)stage_1_frm) + RTCFG_ADDRSIZE_IP); memcpy(stage_1_frm->server_addr, &(rtdev->local_ip), 4); stage_1_frm = (struct rtcfg_frm_stage_1_cfg *) (((u8 *)stage_1_frm) + RTCFG_ADDRSIZE_IP); } #endif /* CONFIG_RTNET_RTIPV4 */ stage_1_frm->burstrate = device[conn->ifindex].burstrate; stage_1_frm->cfg_len = htons(conn->stage1_size); memcpy(rtskb_put(rtskb, conn->stage1_size), conn->stage1_data, conn->stage1_size); return rtcfg_send_frame(rtskb, rtdev, conn->mac_addr); }
static int rtnet_mgr_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) { PROC_PRINT_VARS; int i; struct rtnet_device *rtdev; unsigned int rtskb_len; PROC_PRINT("\nRTnet\n\n"); PROC_PRINT("Devices:\n"); for (i = 1; i <= MAX_RT_DEVICES; i++) { rtdev = rtdev_get_by_index(i); if (rtdev != NULL) { PROC_PRINT(" %s: %s rxq=%d\n", rtdev->name, (rtdev->flags & IFF_UP) ? "UP" : "DOWN", rtdev->rxqueue_len); rtdev_dereference(rtdev); } } rtskb_len = ALIGN_RTSKB_STRUCT_LEN + SKB_DATA_ALIGN(RTSKB_SIZE); PROC_PRINT("\nrtskb pools current/max: %d / %d\n" "rtskbs current/max: %d / %d\n" "rtskb memory need current/max: %d / %d\n\n", rtskb_pools, rtskb_pools_max, rtskb_amount, rtskb_amount_max, rtskb_amount * rtskb_len, rtskb_amount_max * rtskb_len); PROC_PRINT_DONE; }
int rtcfg_send_simple_frame(int ifindex, int frame_id, u8 *dest_addr) { struct rtnet_device *rtdev; struct rtskb *rtskb; unsigned int rtskb_size; struct rtcfg_frm_simple *simple_frm; rtdev = rtdev_get_by_index(ifindex); if (rtdev == NULL) return -ENODEV; rtskb_size = rtdev->hard_header_len + sizeof(struct rtcfg_frm_simple); rtskb = alloc_rtskb(rtskb_size, &rtcfg_pool); if (rtskb == NULL) { rtdev_dereference(rtdev); return -ENOBUFS; } rtskb_reserve(rtskb, rtdev->hard_header_len); simple_frm = (struct rtcfg_frm_simple *) rtskb_put(rtskb, sizeof(struct rtcfg_frm_simple)); simple_frm->head.id = frame_id; simple_frm->head.version = 0; return rtcfg_send_frame(rtskb, rtdev, (dest_addr) ? dest_addr : rtdev->broadcast); }
static int rtnet_read_proc_devices(char *buf, char **start, off_t offset, int count, int *eof, void *data) { int i; int res; struct rtnet_device *rtdev; RTNET_PROC_PRINT_VARS(80); if (!RTNET_PROC_PRINT("Name\t\tFlags\n")) goto done; for (i = 1; i <= MAX_RT_DEVICES; i++) { rtdev = rtdev_get_by_index(i); if (rtdev != NULL) { res = RTNET_PROC_PRINT("%-15s %s%s%s%s\n", rtdev->name, (rtdev->flags & IFF_UP) ? "UP" : "DOWN", (rtdev->flags & IFF_BROADCAST) ? " BROADCAST" : "", (rtdev->flags & IFF_LOOPBACK) ? " LOOPBACK" : "", (rtdev->flags & IFF_PROMISC) ? " PROMISC" : ""); rtdev_dereference(rtdev); if (!res) break; } } done: RTNET_PROC_PRINT_DONE; }
int rtcfg_send_dead_station(struct rtcfg_connection *conn) { struct rtnet_device *rtdev; struct rtskb *rtskb; unsigned int rtskb_size; struct rtcfg_frm_dead_station *dead_station_frm; rtdev = rtdev_get_by_index(conn->ifindex); if (rtdev == NULL) return -ENODEV; rtskb_size = rtdev->hard_header_len + sizeof(struct rtcfg_frm_dead_station) + #ifdef CONFIG_RTNET_RTIPV4 (((conn->addr_type & RTCFG_ADDR_MASK) == RTCFG_ADDR_IP) ? RTCFG_ADDRSIZE_IP : 0); #else /* !CONFIG_RTNET_RTIPV4 */ 0; #endif /* CONFIG_RTNET_RTIPV4 */ rtskb = alloc_rtskb(rtskb_size, &rtcfg_pool); if (rtskb == NULL) { rtdev_dereference(rtdev); return -ENOBUFS; } rtskb_reserve(rtskb, rtdev->hard_header_len); dead_station_frm = (struct rtcfg_frm_dead_station *) rtskb_put(rtskb, sizeof(struct rtcfg_frm_dead_station)); dead_station_frm->head.id = RTCFG_ID_DEAD_STATION; dead_station_frm->head.version = 0; dead_station_frm->addr_type = conn->addr_type & RTCFG_ADDR_MASK; #ifdef CONFIG_RTNET_RTIPV4 if (dead_station_frm->addr_type == RTCFG_ADDR_IP) { rtskb_put(rtskb, RTCFG_ADDRSIZE_IP); memcpy(dead_station_frm->logical_addr, &(conn->addr.ip_addr), 4); dead_station_frm = (struct rtcfg_frm_dead_station *) (((u8 *)dead_station_frm) + RTCFG_ADDRSIZE_IP); } #endif /* CONFIG_RTNET_RTIPV4 */ /* Ethernet-specific! */ memcpy(dead_station_frm->physical_addr, conn->mac_addr, ETH_ALEN); memset(&dead_station_frm->physical_addr[ETH_ALEN], 0, sizeof(dead_station_frm->physical_addr) - ETH_ALEN); return rtcfg_send_frame(rtskb, rtdev, rtdev->broadcast); }
int rtcfg_send_announce_reply(int ifindex, u8 *dest_mac_addr) { struct rtcfg_device *rtcfg_dev = &device[ifindex]; struct rtnet_device *rtdev; struct rtskb *rtskb; unsigned int rtskb_size; struct rtcfg_frm_announce *announce_rpl; rtdev = rtdev_get_by_index(ifindex); if (rtdev == NULL) return -ENODEV; rtskb_size = rtdev->hard_header_len + sizeof(struct rtcfg_frm_announce) + #ifdef CONFIG_RTNET_RTIPV4 ((rtcfg_dev->spec.clt.addr_type == RTCFG_ADDR_IP) ? RTCFG_ADDRSIZE_IP : 0); #else /* !CONFIG_RTNET_RTIPV4 */ 0; #endif /* CONFIG_RTNET_RTIPV4 */ rtskb = alloc_rtskb(rtskb_size, &rtcfg_pool); if (rtskb == NULL) { rtdev_dereference(rtdev); return -ENOBUFS; } rtskb_reserve(rtskb, rtdev->hard_header_len); announce_rpl = (struct rtcfg_frm_announce *) rtskb_put(rtskb, sizeof(struct rtcfg_frm_announce)); announce_rpl->head.id = RTCFG_ID_ANNOUNCE_REPLY; announce_rpl->head.version = 0; announce_rpl->addr_type = rtcfg_dev->spec.clt.addr_type; #ifdef CONFIG_RTNET_RTIPV4 if (announce_rpl->addr_type == RTCFG_ADDR_IP) { rtskb_put(rtskb, RTCFG_ADDRSIZE_IP); memcpy(announce_rpl->addr, &(rtdev->local_ip), 4); announce_rpl = (struct rtcfg_frm_announce *) (((u8 *)announce_rpl) + RTCFG_ADDRSIZE_IP); } #endif /* CONFIG_RTNET_RTIPV4 */ announce_rpl->flags = rtcfg_dev->flags & RTCFG_FLAG_READY; announce_rpl->burstrate = 0; /* padding field */ return rtcfg_send_frame(rtskb, rtdev, dest_mac_addr); }
int rtcfg_send_announce_new(int ifindex) { struct rtcfg_device *rtcfg_dev = &device[ifindex]; struct rtnet_device *rtdev; struct rtskb *rtskb; unsigned int rtskb_size; struct rtcfg_frm_announce *announce_new; rtdev = rtdev_get_by_index(ifindex); if (rtdev == NULL) return -ENODEV; rtskb_size = rtdev->hard_header_len + sizeof(struct rtcfg_frm_announce) + #ifdef CONFIG_RTNET_RTIPV4 (((rtcfg_dev->spec.clt.addr_type & RTCFG_ADDR_MASK) == RTCFG_ADDR_IP) ? RTCFG_ADDRSIZE_IP : 0); #else /* !CONFIG_RTNET_RTIPV4 */ 0; #endif /* CONFIG_RTNET_RTIPV4 */ rtskb = alloc_rtskb(rtskb_size, &rtcfg_pool); if (rtskb == NULL) { rtdev_dereference(rtdev); return -ENOBUFS; } rtskb_reserve(rtskb, rtdev->hard_header_len); announce_new = (struct rtcfg_frm_announce *) rtskb_put(rtskb, sizeof(struct rtcfg_frm_announce)); announce_new->head.id = RTCFG_ID_ANNOUNCE_NEW; announce_new->head.version = 0; announce_new->addr_type = rtcfg_dev->spec.clt.addr_type; #ifdef CONFIG_RTNET_RTIPV4 if (announce_new->addr_type == RTCFG_ADDR_IP) { rtskb_put(rtskb, RTCFG_ADDRSIZE_IP); memcpy(announce_new->addr, &(rtdev->local_ip), 4); announce_new = (struct rtcfg_frm_announce *) (((u8 *)announce_new) + RTCFG_ADDRSIZE_IP); } #endif /* CONFIG_RTNET_RTIPV4 */ announce_new->flags = rtcfg_dev->flags; announce_new->burstrate = rtcfg_dev->burstrate; return rtcfg_send_frame(rtskb, rtdev, rtdev->broadcast); }
int rtcfg_send_stage_2(struct rtcfg_connection *conn, int send_data) { struct rtnet_device *rtdev; struct rtcfg_device *rtcfg_dev = &device[conn->ifindex]; struct rtskb *rtskb; unsigned int rtskb_size; struct rtcfg_frm_stage_2_cfg *stage_2_frm; size_t total_size; size_t frag_size; rtdev = rtdev_get_by_index(conn->ifindex); if (rtdev == NULL) return -ENODEV; if (send_data) { total_size = conn->stage2_file->size; frag_size = MIN(rtdev->mtu - sizeof(struct rtcfg_frm_stage_2_cfg), total_size); } else { total_size = 0; frag_size = 0; } rtskb_size = rtdev->hard_header_len + sizeof(struct rtcfg_frm_stage_2_cfg) + frag_size; rtskb = alloc_rtskb(rtskb_size, &rtcfg_pool); if (rtskb == NULL) { rtdev_dereference(rtdev); return -ENOBUFS; } rtskb_reserve(rtskb, rtdev->hard_header_len); stage_2_frm = (struct rtcfg_frm_stage_2_cfg *) rtskb_put(rtskb, sizeof(struct rtcfg_frm_stage_2_cfg)); stage_2_frm->head.id = RTCFG_ID_STAGE_2_CFG; stage_2_frm->head.version = 0; stage_2_frm->flags = rtcfg_dev->flags; stage_2_frm->stations = htonl(rtcfg_dev->other_stations); stage_2_frm->heartbeat_period = htons(0); stage_2_frm->cfg_len = htonl(total_size); if (send_data) memcpy(rtskb_put(rtskb, frag_size), conn->stage2_file->buffer, frag_size); conn->cfg_offs = frag_size; return rtcfg_send_frame(rtskb, rtdev, conn->mac_addr); }
int rtcfg_send_announce_new(int ifindex) { struct rtcfg_device *rtcfg_dev = &device[ifindex]; struct rtnet_device *rtdev; struct rtskb *rtskb; unsigned int rtskb_size; struct rtcfg_frm_announce *announce_new; rtdev = rtdev_get_by_index(ifindex); if (rtdev == NULL) return -ENODEV; rtskb_size = rtdev->hard_header_len + sizeof(struct rtcfg_frm_announce) + ((rtcfg_dev->addr_type == RTCFG_ADDR_IP) ? RTCFG_ADDRSIZE_IP : 0); rtskb = alloc_rtskb(rtskb_size, &rtcfg_pool); if (rtskb == NULL) { rtdev_dereference(rtdev); return -ENOBUFS; } rtskb_reserve(rtskb, rtdev->hard_header_len); announce_new = (struct rtcfg_frm_announce *) rtskb_put(rtskb, sizeof(struct rtcfg_frm_announce)); announce_new->head.id = RTCFG_ID_ANNOUNCE_NEW; announce_new->head.version = 0; announce_new->addr_type = rtcfg_dev->addr_type; if (announce_new->addr_type == RTCFG_ADDR_IP) { rtskb_put(rtskb, RTCFG_ADDRSIZE_IP); *(u32*)announce_new->addr = rtdev->local_ip; announce_new = (struct rtcfg_frm_announce *) (((u8 *)announce_new) + RTCFG_ADDRSIZE_IP); } announce_new->flags = rtcfg_dev->flags; announce_new->burstrate = rtcfg_dev->burstrate; return rtcfg_send_frame(rtskb, rtdev, rtdev->broadcast); }
static void rtcfg_conn_check_heartbeat(struct rtcfg_connection *conn) { u64 timeout; struct rtcfg_device *rtcfg_dev; timeout = device[conn->ifindex].spec.srv.heartbeat_timeout; if (!timeout) return; if (rtdm_clock_read() >= conn->last_frame + timeout) { rtcfg_dev = &device[conn->ifindex]; rtcfg_dev->stations_found--; rtcfg_dev->stations_ready--; rtcfg_dev->spec.srv.clients_configured--; rtcfg_send_dead_station(conn); rtcfg_next_conn_state(conn, RTCFG_CONN_DEAD); conn->cfg_offs = 0; conn->flags = 0; #ifdef CONFIG_RTNET_RTIPV4 if ((conn->addr_type & RTCFG_ADDR_MASK) == RTCFG_ADDR_IP) { struct rtnet_device *rtdev = rtdev_get_by_index(conn->ifindex); rt_ip_route_del_host(conn->addr.ip_addr, rtdev); if (rtdev == NULL) return; if (!(conn->addr_type & FLAG_ASSIGN_ADDR_BY_MAC)) /* MAC address yet unknown -> use broadcast address */ memcpy(conn->mac_addr, rtdev->broadcast, MAX_ADDR_LEN); rtdev_dereference(rtdev); } #endif /* CONFIG_RTNET_RTIPV4 */ } }
int rtcfg_send_stage_2_frag(struct rtcfg_connection *conn) { struct rtnet_device *rtdev; struct rtskb *rtskb; unsigned int rtskb_size; struct rtcfg_frm_stage_2_cfg_frag *stage_2_frm; size_t frag_size; rtdev = rtdev_get_by_index(conn->ifindex); if (rtdev == NULL) return -ENODEV; frag_size = MIN(rtdev->get_mtu(rtdev, RTCFG_SKB_PRIO) - sizeof(struct rtcfg_frm_stage_2_cfg_frag), conn->stage2_file->size - conn->cfg_offs); rtskb_size = rtdev->hard_header_len + sizeof(struct rtcfg_frm_stage_2_cfg_frag) + frag_size; rtskb = alloc_rtskb(rtskb_size, &rtcfg_pool); if (rtskb == NULL) { rtdev_dereference(rtdev); return -ENOBUFS; } rtskb_reserve(rtskb, rtdev->hard_header_len); stage_2_frm = (struct rtcfg_frm_stage_2_cfg_frag *) rtskb_put(rtskb, sizeof(struct rtcfg_frm_stage_2_cfg_frag)); stage_2_frm->head.id = RTCFG_ID_STAGE_2_CFG_FRAG; stage_2_frm->head.version = 0; stage_2_frm->frag_offs = htonl(conn->cfg_offs); memcpy(rtskb_put(rtskb, frag_size), conn->stage2_file->buffer + conn->cfg_offs, frag_size); conn->cfg_offs += frag_size; return rtcfg_send_frame(rtskb, rtdev, conn->mac_addr); }
/*** * rt_packet_getsockname */ int rt_packet_getsockname(struct rtsocket *sock, struct sockaddr *addr, socklen_t *addrlen) { struct sockaddr_ll *sll = (struct sockaddr_ll*)addr; struct rtnet_device *rtdev; rtdm_lockctx_t context; if (*addrlen < sizeof(struct sockaddr_ll)) return -EINVAL; rtdm_lock_get_irqsave(&sock->param_lock, context); sll->sll_family = AF_PACKET; sll->sll_ifindex = sock->prot.packet.ifindex; sll->sll_protocol = sock->protocol; rtdm_lock_put_irqrestore(&sock->param_lock, context); rtdev = rtdev_get_by_index(sll->sll_ifindex); if (rtdev != NULL) { sll->sll_hatype = rtdev->type; sll->sll_halen = rtdev->addr_len; memcpy(sll->sll_addr, rtdev->dev_addr, rtdev->addr_len); rtdev_dereference(rtdev); } else { sll->sll_hatype = 0; sll->sll_halen = 0; } *addrlen = sizeof(struct sockaddr_ll); return 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 };
/*** * 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; }
int __init rtcap_init(void) { struct rtnet_device *rtdev; struct net_device *dev; int ret; int devices = 0; int i; unsigned long flags; printk("RTcap: real-time capturing interface\n"); #if defined(CONFIG_RTAI_24) || defined(CONFIG_RTAI_30) || defined(CONFIG_RTAI_31) if (start_timer) { rt_set_oneshot_mode(); start_rt_timer(0); } #endif rtskb_queue_init(&cap_queue); ret = rtos_nrt_signal_init(&cap_signal, rtcap_signal_handler); if (ret < 0) goto error1; for (i = 0; i < MAX_RT_DEVICES; i++) { tap_device[i].present = 0; rtdev = rtdev_get_by_index(i); if (rtdev != NULL) { down(&rtdev->nrt_sem); if (test_bit(PRIV_FLAG_UP, &rtdev->priv_flags)) { up(&rtdev->nrt_sem); printk("RTcap: %s busy, skipping device!\n", rtdev->name); rtdev_dereference(rtdev); continue; } if (rtdev->mac_priv != NULL) { up(&rtdev->nrt_sem); printk("RTcap: RTmac discipline already active on device %s. " "Load RTcap before RTmac!\n", rtdev->name); rtdev_dereference(rtdev); continue; } memset(&tap_device[i].tap_dev_stats, 0, sizeof(struct net_device_stats)); dev = &tap_device[i].tap_dev; memset(dev, 0, sizeof(struct net_device)); dev->init = tap_dev_init; dev->priv = rtdev; strncpy(dev->name, rtdev->name, IFNAMSIZ-1); dev->name[IFNAMSIZ-1] = 0; ret = register_netdev(dev); if (ret < 0) { up(&rtdev->nrt_sem); rtdev_dereference(rtdev); printk("RTcap: unable to register %s!\n", dev->name); goto error2; } tap_device[i].present = TAP_DEV; tap_device[i].orig_xmit = rtdev->hard_start_xmit; if ((rtdev->flags & IFF_LOOPBACK) == 0) { dev = &tap_device[i].rtmac_tap_dev; memset(dev, 0, sizeof(struct net_device)); dev->init = tap_dev_init; dev->priv = rtdev; strncpy(dev->name, rtdev->name, IFNAMSIZ-1); dev->name[IFNAMSIZ-1] = 0; strncat(dev->name, "-mac", IFNAMSIZ-strlen(dev->name)); ret = register_netdev(dev); if (ret < 0) { up(&rtdev->nrt_sem); rtdev_dereference(rtdev); printk("RTcap: unable to register %s!\n", dev->name); goto error2; } tap_device[i].present |= RTMAC_TAP_DEV; rtdev->hard_start_xmit = rtcap_xmit_hook; } else rtdev->hard_start_xmit = rtcap_loopback_xmit_hook; /* If the device requires no xmit_lock, start_xmit points equals * hard_start_xmit => we have to update this as well */ if (rtdev->features & RTNETIF_F_NON_EXCLUSIVE_XMIT) rtdev->start_xmit = rtdev->hard_start_xmit; tap_device[i].present |= XMIT_HOOK; __MOD_INC_USE_COUNT(rtdev->owner); up(&rtdev->nrt_sem); devices++; } } if (devices == 0) { printk("RTcap: no real-time devices found!\n"); ret = -ENODEV; goto error2; } if (rtskb_pool_init(&cap_pool, rtcap_rtskbs * devices) < rtcap_rtskbs * devices) { rtskb_pool_release(&cap_pool); ret = -ENOMEM; goto error2; } /* register capturing handlers with RTnet core */ rtos_spin_lock_irqsave(&rtcap_lock, flags); rtcap_handler = rtcap_rx_hook; rtos_spin_unlock_irqrestore(&rtcap_lock, flags); return 0; error2: cleanup_tap_devices(); rtos_nrt_signal_delete(&cap_signal); error1: #if defined(CONFIG_RTAI_24) || defined(CONFIG_RTAI_30) || defined(CONFIG_RTAI_31) if (start_timer) stop_rt_timer(); #endif return ret; }
/*** * 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; }
/*** * rt_packet_sendmsg */ int rt_packet_sendmsg(struct rtsocket *sock, const struct msghdr *msg, size_t len, int flags) { struct sockaddr_ll *sll = (struct sockaddr_ll*)msg->msg_name; struct rtnet_device *rtdev; struct rtskb *rtskb; int ret = 0; if (flags & MSG_OOB) /* Mirror BSD error message compatibility */ return -EOPNOTSUPP; /* a lot of sanity checks */ if ((flags & ~MSG_DONTWAIT) || (sll == NULL) || (msg->msg_namelen != sizeof(struct sockaddr_ll)) || ((sll->sll_family != AF_PACKET) && (sll->sll_family != AF_UNSPEC)) || (sll->sll_ifindex <= 0)) return -EINVAL; if ((rtdev = rtdev_get_by_index(sll->sll_ifindex)) == NULL) return -ENODEV; rtskb = alloc_rtskb(rtdev->hard_header_len + len, &sock->skb_pool); if (rtskb == NULL) { ret = -ENOBUFS; goto out; } if ((len < 0) || (len > rtdev->mtu)) { ret = -EMSGSIZE; goto err; } if (sll->sll_halen != rtdev->addr_len) { ret = -EINVAL; goto err; } rtskb_reserve(rtskb, rtdev->hard_header_len); rt_memcpy_fromkerneliovec(rtskb_put(rtskb, len), msg->msg_iov, len); rtskb->rtdev = rtdev; rtskb->priority = sock->priority; if (rtdev->hard_header) { ret = rtdev->hard_header(rtskb, rtdev, ntohs(sll->sll_protocol), sll->sll_addr, rtdev->dev_addr, rtskb->len); if (ret < 0) goto err; } if ((rtdev->flags & IFF_UP) != 0) { if (rtdev_xmit(rtskb) == 0) ret = len; else ret = -EAGAIN; } else { ret = -ENETDOWN; goto err; } out: rtdev_dereference(rtdev); return ret; err: kfree_rtskb(rtskb); rtdev_dereference(rtdev); return ret; }