/* Notes: * o rtcfg_client_recv_announce does not release the passed rtskb. * o On success, rtcfg_client_recv_announce returns without releasing the * device lock. */ static int rtcfg_client_recv_announce(int ifindex, struct rtskb *rtskb) { struct rtcfg_frm_announce *announce_frm; struct rtcfg_device *rtcfg_dev = &device[ifindex]; u32 i; int result; announce_frm = (struct rtcfg_frm_announce *)rtskb->data; if (rtskb->len < sizeof(struct rtcfg_frm_announce)) { rtos_res_unlock(&rtcfg_dev->dev_lock); RTCFG_DEBUG(1, "RTcfg: received invalid announce frame (id: %d)\n", announce_frm->head.id); return -EINVAL; } switch (announce_frm->addr_type) { #ifdef CONFIG_RTNET_RTIPV4 case RTCFG_ADDR_IP: if (rtskb->len < sizeof(struct rtcfg_frm_announce) + RTCFG_ADDRSIZE_IP) { rtos_res_unlock(&rtcfg_dev->dev_lock); RTCFG_DEBUG(1, "RTcfg: received invalid announce frame " "(id: %d)\n", announce_frm->head.id); return -EINVAL; } /* update routing table */ rt_ip_route_add_host(*(u32 *)announce_frm->addr, rtskb->mac.ethernet->h_source, rtskb->rtdev); announce_frm = (struct rtcfg_frm_announce *) (((u8 *)announce_frm) + RTCFG_ADDRSIZE_IP); break; #endif /* CONFIG_RTNET_RTIPV4 */ case RTCFG_ADDR_MAC: /* nothing to do */ break; default: rtos_res_unlock(&rtcfg_dev->dev_lock); RTCFG_DEBUG(1, "RTcfg: unknown addr_type %d in %s()\n", announce_frm->addr_type, __FUNCTION__); return -EINVAL; } for (i = 0; i < rtcfg_dev->stations_found; i++) /* Ethernet-specific! */ if (memcmp(rtcfg_dev->spec.clt.station_addr_list[i].mac_addr, rtskb->mac.ethernet->h_source, ETH_ALEN) == 0) return 0; result = rtcfg_add_to_station_list(rtcfg_dev, rtskb->mac.ethernet->h_source, announce_frm->flags); if (result < 0) rtos_res_unlock(&rtcfg_dev->dev_lock); return result; }
static void rtcfg_client_recv_stage_2_cfg(int ifindex, struct rtskb *rtskb) { struct rtcfg_frm_stage_2_cfg *stage_2_cfg; struct rtcfg_device *rtcfg_dev = &device[ifindex]; size_t data_len; int ret; if (rtskb->len < sizeof(struct rtcfg_frm_stage_2_cfg)) { rtos_res_unlock(&rtcfg_dev->dev_lock); RTCFG_DEBUG(1, "RTcfg: received invalid stage_2_cfg frame\n"); kfree_rtskb(rtskb); return; } stage_2_cfg = (struct rtcfg_frm_stage_2_cfg *)rtskb->data; __rtskb_pull(rtskb, sizeof(struct rtcfg_frm_stage_2_cfg)); if (stage_2_cfg->heartbeat_period) { ret = rtos_task_init_periodic(&rtcfg_dev->timer_task, rtcfg_timer, (void *)ifindex, RTOS_LOWEST_RT_PRIORITY, ((nanosecs_t)ntohs(stage_2_cfg->heartbeat_period)) * 1000000); if (ret < 0) /*ERRMSG*/rtos_print("RTcfg: unable to create timer task\n"); else rtcfg_dev->flags |= FLAG_TIMER_STARTED; } /* add server to station list */ if (rtcfg_add_to_station_list(rtcfg_dev, rtskb->mac.ethernet->h_source, stage_2_cfg->flags) < 0) { rtos_res_unlock(&rtcfg_dev->dev_lock); RTCFG_DEBUG(1, "RTcfg: unable to process stage_2_cfg frage\n"); kfree_rtskb(rtskb); return; } rtcfg_dev->other_stations = ntohl(stage_2_cfg->stations); rtcfg_dev->spec.clt.cfg_len = ntohl(stage_2_cfg->cfg_len); data_len = MIN(rtcfg_dev->spec.clt.cfg_len, rtskb->len); if (((rtcfg_dev->flags & RTCFG_FLAG_STAGE_2_DATA) != 0) && (data_len > 0)) { rtcfg_client_queue_frag(ifindex, rtskb, data_len); rtskb = NULL; if (rtcfg_dev->stations_found == rtcfg_dev->other_stations) rtcfg_next_main_state(ifindex, RTCFG_MAIN_CLIENT_ALL_KNOWN); } else { if (rtcfg_dev->stations_found == rtcfg_dev->other_stations) { rtcfg_complete_cmd(ifindex, RTCFG_CMD_ANNOUNCE, 0); rtcfg_next_main_state(ifindex, ((rtcfg_dev->flags & RTCFG_FLAG_READY) != 0) ? RTCFG_MAIN_CLIENT_READY : RTCFG_MAIN_CLIENT_2); } else rtcfg_next_main_state(ifindex, RTCFG_MAIN_CLIENT_ALL_FRAMES); rtcfg_send_ack(ifindex); } rtos_res_unlock(&rtcfg_dev->dev_lock); if (rtskb != NULL) kfree_rtskb(rtskb); }
static void rtcfg_client_recv_stage_2_cfg(int ifindex, struct rtskb *rtskb) { struct rtcfg_frm_stage_2_cfg *stage_2_cfg; struct rtcfg_device *rtcfg_dev = &device[ifindex]; size_t data_len; int ret; if (rtskb->len < sizeof(struct rtcfg_frm_stage_2_cfg)) { rtdm_mutex_unlock(&rtcfg_dev->dev_mutex); RTCFG_DEBUG(1, "RTcfg: received invalid stage_2_cfg frame\n"); kfree_rtskb(rtskb); return; } stage_2_cfg = (struct rtcfg_frm_stage_2_cfg *)rtskb->data; __rtskb_pull(rtskb, sizeof(struct rtcfg_frm_stage_2_cfg)); if (stage_2_cfg->heartbeat_period) { ret = rtdm_timer_init(&rtcfg_dev->timer, rtcfg_timer, "rtcfg-timer"); if (ret == 0) { ret = rtdm_timer_start(&rtcfg_dev->timer, XN_INFINITE, (nanosecs_rel_t)ntohs(stage_2_cfg->heartbeat_period) * 1000000, RTDM_TIMERMODE_RELATIVE); if (ret < 0) rtdm_timer_destroy(&rtcfg_dev->timer); } if (ret < 0) /*ERRMSG*/rtdm_printk("RTcfg: unable to create timer task\n"); else set_bit(FLAG_TIMER_STARTED, &rtcfg_dev->flags); } /* add server to station list */ if (rtcfg_add_to_station_list(rtcfg_dev, rtskb->mac.ethernet->h_source, stage_2_cfg->flags) < 0) { rtdm_mutex_unlock(&rtcfg_dev->dev_mutex); RTCFG_DEBUG(1, "RTcfg: unable to process stage_2_cfg frage\n"); kfree_rtskb(rtskb); return; } rtcfg_dev->other_stations = ntohl(stage_2_cfg->stations); rtcfg_dev->spec.clt.cfg_len = ntohl(stage_2_cfg->cfg_len); data_len = MIN(rtcfg_dev->spec.clt.cfg_len, rtskb->len); if (test_bit(RTCFG_FLAG_STAGE_2_DATA, &rtcfg_dev->flags) && (data_len > 0)) { rtcfg_client_queue_frag(ifindex, rtskb, data_len); rtskb = NULL; if (rtcfg_dev->stations_found == rtcfg_dev->other_stations) rtcfg_next_main_state(ifindex, RTCFG_MAIN_CLIENT_ALL_KNOWN); } else { if (rtcfg_dev->stations_found == rtcfg_dev->other_stations) { rtcfg_complete_cmd(ifindex, RTCFG_CMD_ANNOUNCE, 0); rtcfg_next_main_state(ifindex, test_bit(RTCFG_FLAG_READY, &rtcfg_dev->flags) ? RTCFG_MAIN_CLIENT_READY : RTCFG_MAIN_CLIENT_2); } else rtcfg_next_main_state(ifindex, RTCFG_MAIN_CLIENT_ALL_FRAMES); rtcfg_send_ack(ifindex); } rtdm_mutex_unlock(&rtcfg_dev->dev_mutex); if (rtskb != NULL) kfree_rtskb(rtskb); }