void dataman_run(struct dataman *dm) { time_t timer = cw_timer_start(2); dm->nc->process_packet=netconn_process_packet; dm->nc->process_message=dataman_process_message0; dm->nc->data = dm; while (!cw_timer_timeout(timer)){ netconn_read_messages(dm->nc); } if (!dm->wtpman){ cw_log(LOG_ERR,"Data session not associated"); dataman_destroy(dm); return; } cw_dbg(DBG_X,"Data channel established"); dm->nc->process_message=dataman_process_message; while (1){ time_t timer = cw_timer_start(2); while (!cw_timer_timeout(timer)){ netconn_read_messages(dm->nc); } } }
static void wtpman_run_discovery(void *arg) { struct wtpman *wtpman = (struct wtpman *) arg; time_t timer = cw_timer_start(10); extern cw_actionlist_in_t the_tree; wtpman->conn->capwap_state = CW_STATE_DISCOVERY; wtpman->conn->actions = &capwap_actions; wtpman->conn->outgoing = mbag_create(); wtpman->conn->incomming = mbag_create(); while (!cw_timer_timeout(timer) && wtpman->conn->capwap_state == CW_STATE_DISCOVERY) { cw_read_messages(wtpman->conn); } struct mbag_item *wn = mbag_get(wtpman->conn->incomming, CW_ITEM_WTP_NAME); if (wn) { // printf("WTP Name: %s\n", wn->data); // exit(0); } wtpman_remove(wtpman); return; }
static void wtpman_run_discovery(void *arg) { struct wtpman *wtpman = (struct wtpman *) arg; time_t timer = cw_timer_start(10); wtpman->conn->capwap_state = CAPWAP_STATE_DISCOVERY; while (!cw_timer_timeout(timer) && wtpman->conn->capwap_state == CAPWAP_STATE_DISCOVERY) { int rc; rc = cw_read_messages(wtpman->conn); if (cw_result_is_ok(rc)){ wtpman->conn->capwap_state=CAPWAP_STATE_JOIN; cw_dbg(DBG_INFO,"Discovery has detected mods: %s %s", wtpman->conn->cmod->name,wtpman->conn->bmod->name); wtplist_lock(); discovery_cache_add(discovery_cache,(struct sockaddr*)&wtpman->conn->addr, wtpman->conn->cmod,wtpman->conn->bmod); wtplist_unlock(); } } return; }
int run() { struct conn *conn = get_conn(); conn->capwap_state = CW_STATE_RUN; do { int echo_interval = mbag_get_word(conn->config,CW_ITEM_CAPWAP_TIMERS,CAPWAP_TIMERS)&0xff; time_t timer = cw_timer_start(echo_interval); int rc; while (!cw_timer_timeout(timer) && conn->capwap_state == CW_STATE_RUN) { rc = cw_read_messages(conn); if (rc < 0 && errno == EAGAIN) { continue; } if ( !cw_rcok(rc)) break; } if (rc<0 && errno == EAGAIN){ rc = cw_send_request(conn,CW_MSG_ECHO_REQUEST); if (!cw_rcok(rc)) { cw_log(LOG_ERR,"Error in run state: %d %s",rc,cw_strrc(rc)); break; } continue; } if (!cw_rcok(rc)) { cw_log(LOG_ERR,"Error in run state: %d %s",rc,cw_strrc(rc)); break; } } while (conn->capwap_state == CW_STATE_RUN); // int rc = cw_send_request(conn,CW_MSG_CHANGE_STATE_EVENT_REQUEST); // if ( !cw_rcok(rc) ) { // cw_strresult(rc); // } return 0; }
static void reset_echointerval_timer(struct wtpman *wtpman) { uint16_t ct = mbag_get_word(wtpman->conn->local, CW_ITEM_CAPWAP_TIMERS, CAPWAP_MAX_DISCOVERY_INTERVAL << 8 | CAPWAP_ECHO_INTERVAL); /* start echinterval timer and put 2 seconds for "safety" on it */ wtpman->echointerval_timer = cw_timer_start(2+ (ct & 0xff)); db_ping_wtp(sock_addr2str_p(&wtpman->conn->addr), conf_acname); // cw_dbg(DBG_X, "Starting capwap timer: %d", wtpman->echointerval_timer); }
int cw_send_request(struct conn *conn,int msg_id) { time_t timer; int i; int rc; char sock_buf[SOCK_ADDR_BUFSIZE]; cw_init_request(conn, msg_id); if ( cw_put_msg(conn, conn->req_buffer) == -1 ){ errno=ENOMSG; return -1; } conn_send_msg(conn, conn->req_buffer); rc=-1; for (i=0; i<conn->max_retransmit && rc<0; i++){ if ( i>0 ){ cw_log(LOG_WARNING,"Retransmitting request ... %d",i); } timer = cw_timer_start(conn->retransmit_interval); while (!cw_timer_timeout(timer) && rc<0){ rc =cw_read_messages(conn); if(rc<0){ if (errno!=EAGAIN) break; } } if (rc<0){ if(errno!=EAGAIN) break; } } if ( rc <0 && errno != EAGAIN) { cw_log(LOG_ERR,"Can't read from %s: %s",sock_addr2str(&conn->addr,sock_buf),strerror(errno)); } if ( rc <0 && errno == EAGAIN) { errno=ETIMEDOUT; rc=-1; } return rc; }
int dtls_gnutls_bio_wait(gnutls_transport_ptr_t ptr, unsigned int ms) { struct conn * conn = (struct conn*)ptr; time_t timer = cw_timer_start(ms/1000); int rc; uint8_t buffer[5]; do { rc = conn->recv_packet_peek(conn,buffer,sizeof(buffer)); }while(!cw_timer_timeout(timer) && rc==GNUTLS_E_AGAIN); return rc; }
static int wtpman_join(void *arg) { int rc; char sock_buf[SOCK_ADDR_BUFSIZE]; struct wtpman *wtpman = (struct wtpman *) arg; struct conn *conn = wtpman->conn; time_t timer, wait_join; cw_dbg(DBG_INFO, "Join State - %s", sock_addr2str(&conn->addr,sock_buf)); wait_join = cw_ktv_get_word(conn->global_cfg,"wait-join",CAPWAP_WAIT_JOIN); timer = cw_timer_start(wait_join); while (!cw_timer_timeout(timer) && wtpman->conn->capwap_state == CAPWAP_STATE_JOIN) { rc = cw_read_messages(wtpman->conn); if (rc < 0) { if (errno == EAGAIN) continue; break; } cw_dbg_ktv_dump(conn->remote_cfg,DBG_INFO, "-------------dump------------", "DMP","---------end dump --------"); } if (rc != 0) { cw_log(LOG_ERR, "Error joining WTP %s", cw_strerror(rc)); return 0; } if (wtpman->conn->capwap_state != CAPWAP_STATE_JOIN_COMPLETE) { cw_dbg(DBG_MSG_ERR, "No join request from %s after %d seconds, WTP died.", sock_addr2str(&wtpman->conn->addr,sock_buf), wait_join); return 0; } return 1; }
int cw_run_state_machine(struct conn * conn, time_t *timer) { int timerval; cw_StateMachineState_t search, *result; while(1){ search.state = conn->capwap_state; search.prevstate = conn->capwap_prevstate; result = mavl_get(conn->msgset->state_machine,&search); cw_dbg(DBG_STATE,"State transition: [%s -> %s]", cw_strstate(conn->capwap_prevstate), cw_strstate(conn->capwap_state) ); if (result == NULL){ cw_log(LOG_ERR,"State not found"); return 0; } if (result->jump_state){ conn->capwap_state = result->jump_state; conn->capwap_prevstate = result->jump_prevstate; cw_dbg(DBG_STATE,"Jump to state: [%s->%s]", cw_strstate(conn->capwap_prevstate), cw_strstate(conn->capwap_state)); continue; } if (result->dbgmsg){ cw_dbg(DBG_STATE,"%s",result->dbgmsg); } if (result->timer_key){ timerval = cw_ktv_get_word(conn->local_cfg,result->timer_key,result->timer_default); *timer = cw_timer_start(timerval); cw_dbg(DBG_STATE,"Starting timer: [%s] - %d seconds.",result->timer_key,timerval); } return result->retval; } }
int dtls_openssl_connect(struct conn *conn) { if (!conn->dtls_data) conn->dtls_data = dtls_openssl_data_create(conn, DTLSv1_client_method(), dtls_openssl_bio_method()); struct dtls_openssl_data *d = (struct dtls_openssl_data *) conn->dtls_data; if (!d) return 0; // if (conn->dtls_psk) // SSL_set_psk_client_callback(d->ssl, psk_client_cb); int rc; errno =0; time_t timer = cw_timer_start(10); do { rc = SSL_connect(d->ssl); }while(rc!=1 && errno==EAGAIN && !cw_timer_timeout(timer)); if (rc == 1) { cw_dbg(DBG_DTLS,"SSL connect successfull!"); conn->read = dtls_openssl_read; conn->write = dtls_openssl_write; return 1; } rc = dtls_openssl_log_error(0, rc, "DTLS connect"); return 0; }
static int run_discovery(struct conn *conn) { // conn->incomming = mbag_create(); conn->capwap_state = CW_STATE_DISCOVERY; mbag_set_byte(conn->outgoing, CW_ITEM_DISCOVERY_TYPE, CW_DISCOVERY_TYPE_UNKNOWN); cw_init_request(conn, CW_MSG_DISCOVERY_REQUEST); cw_put_msg(conn, conn->req_buffer); conn_send_msg(conn, conn->req_buffer); time_t timer = cw_timer_start(0); while (!cw_timer_timeout(timer) && conn->capwap_state == CW_STATE_DISCOVERY) { mavl_del_all(conn->incomming); int rc = cw_read_from(conn); if (rc<0) { if (errno==EAGAIN) continue; cw_log(LOG_ERROR,"Error reading messages: %s",strerror(errno)); break; } } mbag_t discs; discs = mbag_get_mavl(conn->remote, CW_ITEM_DISCOVERIES); if (!discs) { cw_log(LOG_ERR,"No discovery responses received"); return 0; } int i; cw_aciplist_t list = cw_select_ac(conn, discs); DEFINE_AVLITER(ii,list); avliter_foreach(&ii){ cw_acip_t * ip = avliter_get(&ii); } mavl_del_all(conn->remote); mbag_set_mavl(conn->local,CW_ITEM_CAPWAP_CONTROL_IP_ADDRESS_LIST,list); return 1; }
int dtls_gnutls_accept(struct conn *conn) { char sock_buf[SOCK_ADDR_BUFSIZE]; char cookie_buf[SOCK_ADDR_BUFSIZE]; struct dtls_gnutls_data *d; uint8_t buffer[2048]; int tlen, rc; time_t c_timer; int bits; gnutls_datum_t cookie_key; gnutls_dtls_prestate_st prestate; gnutls_key_generate(&cookie_key, GNUTLS_COOKIE_KEY_SIZE); cw_dbg(DBG_DTLS, "Session cookie for %s generated: %s", sock_addr2str(&conn->addr, sock_buf), sock_hwaddrtostr((uint8_t *) (&cookie_key), sizeof(cookie_key), cookie_buf, "")); memset(&prestate, 0, sizeof(prestate)); tlen = dtls_gnutls_bio_read(conn, buffer, sizeof(buffer)); gnutls_dtls_cookie_send(&cookie_key, &conn->addr, sizeof(conn->addr), &prestate, (gnutls_transport_ptr_t) conn, dtls_gnutls_bio_write); rc = -1; c_timer = cw_timer_start(10); while (!cw_timer_timeout(c_timer)) { tlen = conn_q_recv_packet_peek(conn, buffer, sizeof(buffer)); if (tlen < 0 && errno == EAGAIN) continue; if (tlen < 0) { /* something went wrong, we should log a message */ continue; } rc = gnutls_dtls_cookie_verify(&cookie_key, &conn->addr, sizeof(conn->addr), buffer + 4, tlen - 4, &prestate); if (rc < 0) { cw_dbg(DBG_DTLS, "Cookie couldn't be verified: %s", gnutls_strerror(rc)); dtls_gnutls_bio_read(conn, buffer, sizeof(buffer)); continue; } break; } if (rc < 0) { cw_log(LOG_ERR, "Cookie couldn't be verified: %s", gnutls_strerror(rc)); return 0; } cw_dbg(DBG_DTLS, "Cookie verified! Starting handshake with %s ...", sock_addr2str(&conn->addr, sock_buf)); d = dtls_gnutls_data_create(conn, GNUTLS_SERVER | GNUTLS_DATAGRAM); if (!d) return 0; if (conn->dtls_psk_enable) { gnutls_psk_server_credentials_t cred; rc = gnutls_psk_allocate_server_credentials(&cred); if (rc != 0) { cw_log(LOG_ERR,"gnutls_psk_allocate_server_credentials() failed."); } /* GnuTLS will call psk_creds to ask for the key associated with the client's username.*/ gnutls_psk_set_server_credentials_function(cred, psk_creds); /* // Pass the "credentials" to the GnuTLS session. GnuTLS does NOT make an // internal copy of the information, so we have to keep the 'cred' structure // in memory (and not modify it) until we're done with this session.*/ rc = gnutls_credentials_set(d->session, GNUTLS_CRD_PSK, cred); if (rc != 0) { cw_log(LOG_ERR,"gnutls_credentials_set() failed.\n"); } } /* Generate Diffie-Hellman parameters - for use with DHE * kx algorithms. When short bit length is used, it might * be wise to regenerate parameters often. */ /*bits = gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH, GNUTLS_SEC_PARAM_LEGACY); */ bits = conn->dtls_dhbits; gnutls_dh_params_init(&d->dh_params); cw_dbg(DBG_DTLS, "Generating DH params, %d", bits); gnutls_dh_params_generate2(d->dh_params, bits); cw_dbg(DBG_DTLS, "DH params generated, %d", bits); gnutls_certificate_set_dh_params(d->x509_cred, d->dh_params); gnutls_certificate_server_set_request(d->session, GNUTLS_CERT_REQUEST); gnutls_dtls_prestate_set(d->session, &prestate); c_timer = cw_timer_start(10); do { rc = gnutls_handshake(d->session); } while (!cw_timer_timeout(c_timer) && rc == GNUTLS_E_AGAIN); if (rc < 0) { cw_log(LOG_ERR, "Error in handshake with %s: %s", sock_addr2str(&conn->addr, sock_buf), gnutls_strerror(rc)); return 0; } cw_dbg(DBG_DTLS, "Handshake with %s successful.", sock_addr2str(&conn->addr, sock_buf)); conn->dtls_data = d; conn->read = dtls_gnutls_read; conn->write = dtls_gnutls_write; return 1; }
static void wtpman_run(void *arg) { struct wtpman *wtpman = (struct wtpman *) arg; wtpman->conn->seqnum = 0; struct conn *conn = wtpman->conn; /* reject connections to our multi- or broadcast sockets */ /* if (socklist[wtpman->socklistindex].type != SOCKLIST_UNICAST_SOCKET) { cw_dbg(DBG_DTLS, "Dropping connection from %s to non-unicast socket.", CLIENT_IP); wtpman_remove(wtpman); return; } */ time_t timer = cw_timer_start(wtpman->conn->wait_dtls); /* establish dtls session */ /* if (!wtpman_establish_dtls(wtpman)) { wtpman_remove(wtpman); return; } */ /* dtls is established, goto join state */ if (!wtpman_join(wtpman, timer)) { wtpman_remove(wtpman); return; } conn->msg_start = msg_start_handler; cw_dbg(DBG_INFO, "WTP from %s has joined with session id: %s", sock_addr2str_p(&conn->addr), format_bin2hex(conn->session_id,16)); // cw_dbg(DBG_INFO, "Creating data thread"); // pthread_t thread; // pthread_create(&thread, NULL, (void *) wtpman_run_data, (void *) wtpman); /* here the WTP has joined, now we assume an image data request or an configuration status request. Nothing else. */ int rc = 0; while (!cw_timer_timeout(timer) && wtpman->conn->capwap_state == CW_STATE_CONFIGURE) { rc = cw_read_messages(wtpman->conn); if (rc < 0) { if (errno != EAGAIN) break; } } if (!cw_rcok(rc)) { cw_dbg(DBG_INFO, "WTP Problem: %s", cw_strrc(rc)); wtpman_remove(wtpman); return; } if (conn->capwap_state == CW_STATE_IMAGE_DATA) { wtpman_image_data(wtpman); return; } conn->capwap_state = CW_STATE_RUN; // XXX testing ... // DBGX("Cofig to sql", ""); props_to_sql(conn,conn->incomming,0); radios_to_sql(conn); conn->msg_end=msg_end_handler; /* The main run loop */ reset_echointerval_timer(wtpman); rc = 0; while (wtpman->conn->capwap_state == CW_STATE_RUN) { rc = cw_read_messages(wtpman->conn); if (rc < 0) { if (errno != EAGAIN) break; } // cw_dbg(DBG_X, "Time left: %d", // cw_timer_timeleft(wtpman->echointerval_timer)); if (cw_timer_timeout(wtpman->echointerval_timer)) { cw_dbg(DBG_INFO, "Lost connection to WTP:%s", sock_addr2str_p(&conn->addr)); break; } mavl_del_all(conn->outgoing); conn_clear_upd(conn,1); // props_to_sql(conn,conn->incomming,0); // radios_to_sql(conn); mavl_conststr_t r; r = db_get_update_tasks(conn, sock_addr2str(&conn->addr)); if (r) { if (!conn->outgoing->count) continue; cw_dbg(DBG_INFO, "Updating WTP %s",sock_addr2str(&conn->addr)); rc = cw_send_request(conn, CW_MSG_CONFIGURATION_UPDATE_REQUEST); mavl_merge(conn->config, conn->outgoing); mavl_destroy(conn->outgoing); conn->outgoing = mbag_create(); props_to_sql(conn,conn->incomming,0); radios_to_sql(conn); mavl_destroy(r); } r = db_get_radio_tasks(conn, sock_addr2str(&conn->addr)); if (r) { if (!conn->radios_upd->count) continue; cw_dbg(DBG_INFO, "Updating Radios for %s",sock_addr2str(&conn->addr)); rc = cw_send_request(conn, CW_MSG_CONFIGURATION_UPDATE_REQUEST); conn_clear_upd(conn,1); // mavl_destroy(conn->radios_upd); // conn->radios_upd=mbag_i_create(); radios_to_sql(conn); /* rc = cw_send_request(conn, CW_MSG_CONFIGURATION_UPDATE_REQUEST); mavl_merge(conn->config, conn->outgoing); mavl_destroy(conn->outgoing); conn->outgoing = mbag_create(); config_to_sql(conn); radios_to_sql(conn); mavl_destroy(r); */ } } db_ping_wtp(sock_addr2str_p(&conn->addr), ""); wtpman_remove(wtpman); return; }