关于hostapd 消息处理的细节问题,兼答网友第三次问


【 ... 】或

【【...】】之间的是我加的,其他的为代码或问题

按照自己的理解看的,不知对不对。

 

 

1.    在eloop_run()中,最后的对信号的处理,即套接字上有消息的处理是怎么做的,(看到了代码,但是不理解是在做什么,
static void eloop_process_pending_signals(void)
{
    int i;

    if (eloop.signaled == 0)
        return;
    eloop.signaled = 0;

    if (eloop.pending_terminate) {
#ifndef CONFIG_NATIVE_WINDOWS
        alarm(0);
#endif /* CONFIG_NATIVE_WINDOWS */
        eloop.pending_terminate = 0;
    }

    for (i = 0; i < eloop.signal_count; i++) {
        if (eloop.signals[i].signaled) {
            eloop.signals[i].signaled = 0;
【这里开始对收到的信号处理,
这是指
#ifndef CONFIG_NATIVE_WINDOWS
    eloop_register_signal(SIGHUP, handle_reload, NULL);
    eloop_register_signal(SIGUSR1, handle_dump_state, NULL);
#endif /* CONFIG_NATIVE_WINDOWS */
    eloop_register_signal_terminate(handle_term, NULL);
注册的系统信号处理,这还不是你关心的内容了。还有收到TERM的处理】

            eloop.signals[i].handler(eloop.signals[i].sig,
                         eloop.user_data,
                         eloop.signals[i].user_data);
        }
    }
})

eloop_run()是非阻塞socket,那么最后得到的是什么?如果没有返回值,又是做了什么操作?


系统运行期间一直在里面while循环的,
void eloop_run(void)
{
    fd_set *rfds, *wfds, *efds;
    int res;
    struct timeval _tv;
    struct os_time tv, now;

    rfds = os_malloc(sizeof(*rfds));
    wfds = os_malloc(sizeof(*wfds));
    efds = os_malloc(sizeof(*efds));
    if (rfds == NULL || wfds == NULL || efds == NULL) {
        printf("eloop_run - malloc failed/n");
        goto out;
    }

    while (!eloop.terminate &&
           (eloop.timeout || eloop.readers.count > 0 ||
        eloop.writers.count > 0 || eloop.exceptions.count > 0))
 {
 【【正常情况都在这里面循环,除非terminate为1,而这个有信号处理设置.
参见
    eloop_register_signal_terminate(handle_term, NULL);
static void handle_term(int sig, void *eloop_ctx, void *signal_ctx)
{
    wpa_printf(MSG_DEBUG, "Signal %d received - terminating", sig);
    eloop_terminate();
}
void eloop_terminate(void)
{
    eloop.terminate = 1;
}
】】


        if (eloop.timeout) {
            os_get_time(&now);
            if (os_time_before(&now, &eloop.timeout->time))
                os_time_sub(&eloop.timeout->time, &now, &tv);
            else
                tv.sec = tv.usec = 0;
#if 0
            printf("next timeout in %lu.%06lu sec/n",
                   tv.sec, tv.usec);
#endif            _tv.tv_sec = tv.sec;
            _tv.tv_usec = tv.usec;
        }

        eloop_sock_table_set_fds(&eloop.readers, rfds);
        eloop_sock_table_set_fds(&eloop.writers, wfds);
        eloop_sock_table_set_fds(&eloop.exceptions, efds);
        res = select(eloop.max_sock + 1, rfds, wfds, efds,
                 eloop.timeout ? &_tv : NULL);
        if (res < 0 && errno != EINTR && errno != 0) {
            perror("select");
            goto out;
        }
        eloop_process_pending_signals();

        /* check if some registered timeouts have occurred */
        if (eloop.timeout) {
            struct eloop_timeout *tmp;

            os_get_time(&now);
            if (!os_time_before(&now, &eloop.timeout->time)) {
                tmp = eloop.timeout;
                eloop.timeout = eloop.timeout->next;
                tmp->handler(tmp->eloop_data,
                         tmp->user_data);
                os_free(tmp);
            }

        }

        if (res <= 0)
            continue;

        eloop_sock_table_dispatch(&eloop.readers, rfds);
        eloop_sock_table_dispatch(&eloop.writers, wfds);
        eloop_sock_table_dispatch(&eloop.exceptions, efds);
    }

out:
    os_free(rfds);
    os_free(wfds);
    os_free(efds);
}


【【
第一次的时候说到l2_packet_init
struct l2_packet_data * l2_packet_init(
    const char *ifname, const u8 *own_addr, unsigned short protocol,
    void (*rx_callback)(void *ctx, const u8 *src_addr,
                const u8 *buf, size_t len),
    void *rx_callback_ctx, int l2_hdr)
{
    ……
    eloop_register_read_sock(l2->fd, l2_packet_receive, l2, NULL);

    return l2;
}
call  int eloop_register_read_sock(int sock, eloop_sock_handler handler,
                 void *eloop_data, void *user_data)
{  这里handler即l2_packet_receive
    return eloop_register_sock(sock, EVENT_TYPE_READ, handler,
                   eloop_data, user_data);
}
最后通过
static int eloop_sock_table_add_sock(struct eloop_sock_table *table,
                                     int sock, eloop_sock_handler handler,
                                     void *eloop_data, void *user_data)
将socket可读消息的handler回调函数设为了l2_packet_receive,
(其实代码看madwifi还注册了别的,如hostapd.c里面的
    /* TODO: merge with hostapd_driver_init() ? */
    if (hostapd_wireless_event_init(hapd) < 0)
        return -1;有注释说明会给hostapd_drive_init合并
应该也会对这些socket来说也会走到的,进行相应处理,未关注。
)



再回头看eloop_sock_table_dispatch(&eloop.readers, rfds);
static void eloop_sock_table_dispatch(struct eloop_sock_table *table,
                      fd_set *fds)
{
    int i;

    if (table == NULL || table->table == NULL)
        return;

    table->changed = 0;
    for (i = 0; i < table->count; i++) {
        if (FD_ISSET(table->table[i].sock, fds)) {
            table->table[i].handler(table->table[i].sock,
                        table->table[i].eloop_data,
                        table->table[i].user_data);
            if (table->changed)
                break;
        }
    }
}这里的handler就是l2_packet_receive或madwifi_wireless_event_receive等函数


l2_packet_receiv这个有通过第一次说的l2_packet_init设的handle_read执行。
】】


客户端应该是以UDP的形式发包吧?我Device端使用eloop_run()来接收,期间eloop_run()是将EAPOL帧怎样存放的,你在第一次给我的回复中,使用Madwifi初始化中得到的,现在就是从eloop_run()的结果到ieee802_1x_receive()中参数调用*buf的过程不很明确,


认证阶段都没有ip,怎么会是UDP?
再一次看这个,当select到read-sock有消息时,最终call到这里
static void l2_packet_receive(int sock, void *eloop_ctx, void *sock_ctx)
{
    struct l2_packet_data *l2 = eloop_ctx;
    u8 buf[2300];
    int res;
    struct sockaddr_ll ll;
    socklen_t fromlen;

    os_memset(&ll, 0, sizeof(ll));
    fromlen = sizeof(ll);
    res = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *) &ll,
               &fromlen);
这里收raw_socket,注意是L2, 直接读取链路层数据。Res就是消息长度,地址在ll里面。
    if (res < 0) {
        perror("l2_packet_receive - recvfrom");
        return;
    }
这个就是第一次说的handle_read了
    l2->rx_callback(l2->rx_callback_ctx, ll.sll_addr, buf, res);
}



2.对于函数static void handle_eap_response(struct hostapd_data *hapd,
                struct sta_info *sta, struct eap_hdr *eap,
                size_t len)                    ieee802_1x.c
按照理论是应该就收到客户端发来的response(即EAPOL_Response/identity和challenged password两种报文),作为device功能就是将这个报文转发给RADUIS就可以了,我这样的理解是否有问题?如此说来,我就对handle_eap_response()函数的操作看不懂了,没看懂他是怎么实现的这个目的


static void handle_eap_response(struct hostapd_data *hapd,
                struct sta_info *sta, struct eap_hdr *eap,
                size_t len)
{
    u8 type, *data;
    struct eapol_state_machine *sm = sta->eapol_sm;
    if (sm == NULL)
        return;

    data = (u8 *) (eap + 1);

    if (len < sizeof(*eap) + 1) {
        printf("handle_eap_response: too short response data/n");
        return;
    }

    sm->eap_type_supp = type = data[0];

    hostapd_logger(hapd, sm->addr, HOSTAPD_MODULE_IEEE8021X,
               HOSTAPD_LEVEL_DEBUG, "received EAP packet (code=%d "
               "id=%d len=%d) from STA: EAP Response-%s (%d)",
               eap->code, eap->identifier, be_to_host16(eap->length),
               eap_type_text(type), type);

    sm->dot1xAuthEapolRespFramesRx++;

    wpabuf_free(sm->eap_if->eapRespData);
    sm->eap_if->eapRespData = wpabuf_alloc_copy(eap, len);
    sm->eapolEap = TRUE;
}

请指教。


【A:
ieee802_1x_receive
1{
if     IEEE802_1X_TYPE_EAP_PACKET
    2{
call        handle_eap
            3{
            if response
                     call handle_eap_response 
exec sm->eap_if->eapRespData = wpabuf_alloc_copy(eap, len);设置好respData即可
            3}
    2}
    //执行状态机,里面完成转发等系列
    eapol_auth_step(sta->eapol_sm);

1}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值