void show_aps (FILE *out) { struct connlist * cl; mavliter_t it; wtplist_lock(); cl = wtplist_get_connlist(); mavliter_init (&it, cl->by_addr); fprintf (out, "IP\t\t\twtp-name\n"); mavliter_foreach (&it) { cw_KTV_t * result; char addr[SOCK_ADDR_BUFSIZE]; char wtp_name[CAPWAP_MAX_WTP_NAME_LEN]; struct conn * conn; conn = mavliter_get_ptr (&it); sock_addr2str_p (&conn->addr, addr); result = cw_ktv_get (conn->remote_cfg, "wtp-name", NULL); if (result == NULL) { strcpy (wtp_name, ""); } else { result->type->to_str (result, wtp_name, CAPWAP_MAX_WTP_NAME_LEN); } fprintf (out, "%s\t\t%s\n", addr, wtp_name); } wtplist_unlock(); }
static int wtpman_establish_dtls(void *arg) { struct wtpman *wtpman = (struct wtpman *) arg; /* setup cipher */ wtpman->conn->dtls_cipher = conf_sslcipher; /* setup DTSL certificates */ int dtls_ok = 0; if (conf_sslkeyfilename && conf_sslcertfilename) { wtpman->conn->dtls_key_file = conf_sslkeyfilename; wtpman->conn->dtls_cert_file = conf_sslcertfilename; wtpman->conn->dtls_key_pass = conf_sslkeypass; wtpman->conn->dtls_verify_peer = conf_dtls_verify_peer; cw_dbg(DBG_DTLS, "Using key file %s", wtpman->conn->dtls_key_file); cw_dbg(DBG_DTLS, "Using cert file %s", wtpman->conn->dtls_cert_file); dtls_ok = 1; } /* setup DTLS psk */ if (conf_dtls_psk) { wtpman->conn->dtls_psk = conf_dtls_psk; wtpman->conn->dtls_psk_len = strlen(conf_dtls_psk); dtls_ok = 1; } if (!dtls_ok) { cw_log(LOG_ERR, "Can't establish DTLS session, neither psk nor certs set in config file."); return 0; } /* try to accept the connection */ if (!dtls_accept(wtpman->conn)) { cw_dbg(DBG_DTLS, "Error establishing DTLS session with %s", sock_addr2str_p(&wtpman->conn->addr)); return 0; } cw_dbg(DBG_DTLS, "DTLS session established with %s, cipher=%s", sock_addr2str_p(&wtpman->conn->addr), dtls_get_cipher(wtpman->conn)); return 1; }
static int wtpman_dtls_setup(void *arg) { char cipherstr[512]; char sock_buf[SOCK_ADDR_BUFSIZE]; struct wtpman *wtpman = (struct wtpman *) arg; /* try to accept the connection */ if (!dtls_accept(wtpman->conn)) { cw_dbg(DBG_DTLS, "Error establishing DTLS session with %s", sock_addr2str_p(&wtpman->conn->addr,sock_buf)); return 0; } cw_dbg(DBG_DTLS, "DTLS session established with %s, %s", sock_addr2str_p(&wtpman->conn->addr,sock_buf), dtls_get_cipher(wtpman->conn,cipherstr)); return 1; }
static struct cw_actiondef *load_mods(struct conn *conn, uint8_t * rawmsg, int len, int elems_len, struct sockaddr *from) { struct mod_ac *cmod = detect_mod(conn, rawmsg, len, elems_len, from, MOD_MODE_CAPWAP); if (cmod == MOD_NULL) { cw_dbg(DBG_MSG_ERR, "Can't find mod to handle connection from %s , discarding message", sock_addr2str_p(from)); return NULL; } struct mod_ac *bmod = detect_mod(conn, rawmsg, len, elems_len, from, MOD_MODE_BINDINGS); cw_dbg(DBG_INFO, "Mods deteced: %s,%s", cmod->name, bmod->name); struct cw_actiondef *ad = mod_cache_add(conn,cmod, bmod); return ad; /* if (bindins_mod) { cw_dbg(DBG_INFO, "Using mod '%s' to handle CAWPAP for %s", mod->name, sock_addr2str_p(from)); conn->detected=1; } else{ // errno = EAGAIN; // return -1; } mod = detect_mod(conn, rawmsg, len, elems_len, from, MOD_DETECT_BINDINGS); if (mod) { cw_dbg(DBG_INFO, "Using bindings '%s' to handle %s", mod->name, sock_addr2str_p(from)); conn->detected=1; } else{ cw_dbg(DBG_MSG_ERR, "Can't detect bindings ... for %s", sock_addr2str_p(from)); } 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); }
void con (FILE *out) { struct connlist * cl; mavliter_t it; wtplist_lock(); cl = wtplist_get_connlist(); mavliter_init (&it, cl->by_addr); fprintf (out, "IP\t\t\twtp-name\n"); mavliter_foreach (&it) { cw_KTV_t * result; char addr[SOCK_ADDR_BUFSIZE]; char wtp_name[CAPWAP_MAX_WTP_NAME_LEN]; struct conn * conn; conn = mavliter_get_ptr (&it); sock_addr2str_p (&conn->addr, addr); result = cw_ktv_get (conn->remote_cfg, "wtp-name", NULL); if (result == NULL) { strcpy (wtp_name, ""); } else { result->type->to_str (result, wtp_name, CAPWAP_MAX_WTP_NAME_LEN); } fprintf (out, "Con!! %s\t\t%s\n", addr, wtp_name); { mavl_t update; update = cw_ktv_create(); cw_ktv_set_byte(update,"radio.255/admin-state",1); conn->update_cfg=update; } fprintf(out,"\n"); } wtplist_unlock(); }
static void wtpman_run_dtls(void *arg) { char sock_buf[SOCK_ADDR_BUFSIZE]; struct wtpman *wtpman = (struct wtpman *) arg; /* 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.", sock_addr2str_p(&wtpman->conn->addr,sock_buf)); wtpman_remove(wtpman); return; } /*// time_t timer = cw_timer_start(wtpman->conn->wait_dtls);*/ /* establish dtls session */ if (!wtpman_dtls_setup(wtpman)) { wtpman_remove(wtpman); return; } wtpman_main(arg); }
void * run_shell (void * arg) { struct sockaddr_storage server, client; socklen_t client_size; char sockstr[SOCK_ADDR_BUFSIZE]; int rc; const char * addr = "127.0.0.1:5000"; int sockfd, clientsock; int yes; while(1){ rc = sock_strtoaddr (addr, (struct sockaddr*) &server); if (! rc) { cw_log (LOG_ERR, "Can't parse address '%s', %s", addr, strerror (errno)); } sockfd = socket ( ( (struct sockaddr*) &server)->sa_family, SOCK_STREAM, 0); yes = 1; /* reuse address */ setsockopt (sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof (yes)); /* bind address */ rc = bind (sockfd, (struct sockaddr*) &server, sizeof (server)); if (rc) { cw_log (LOG_ERR, "Can't bind socket address '%s', %s", addr, strerror (errno)); } rc = listen (sockfd, 5); if (rc) { cw_log (LOG_ERR, "Can't listen on address '%s', %s", addr, strerror (errno)); } client_size = sizeof (client); clientsock = accept (sockfd, (struct sockaddr*) &client, &client_size); if (clientsock > 0) { sock_addr2str_p (&client, sockstr); cw_dbg (DBG_INFO, "Acceptiong session from %s", sockstr); printf("New shell lopp\n"); shell_loop (fdopen (clientsock, "a+")); printf("end shell lopp\n"); close (clientsock); printf("close clsock\n"); } cw_dbg (DBG_INFO,"Accepting shell session %i, %s", rc, strerror (errno)); } return NULL; }
static void * wtpman_main(void *arg) { mavl_t r; int rc ; time_t timer; char sock_buf[SOCK_ADDR_BUFSIZE]; struct conn *conn; int last_state; struct wtpman *wtpman = (struct wtpman *) arg; wtpman->conn->seqnum = 0; conn = wtpman->conn; wtpman->conn->remote_cfg = cw_ktv_create(); /* We were invoked with an unencrypted packet, * so assume, it is a discovery request */ if (!wtpman->dtlsmode){ wtpman_run_discovery(arg); wtpman_remove(wtpman); return NULL; } /* reject connections to our multi- or broadcast sockets */ if (socklist[wtpman->socklistindex].type != SOCKLIST_UNICAST_SOCKET) { cw_dbg(DBG_DTLS,"Reject multi"); wtpman_remove(wtpman); return NULL; } conn->capwap_state = CAPWAP_STATE_DTLS_SETUP; /* establish dtls session */ if (!wtpman_dtls_setup(wtpman)) { wtpman_remove(wtpman); return NULL; } /*last_state = conn->capwap_state; conn->capwap_state = CAPWAP_STATE_JOIN; */ conn->capwap_prevstate = CAPWAP_STATE_DTLS_SETUP; conn->capwap_state = CAPWAP_STATE_JOIN; rc = 0; while (1){ int wait_join; int wait_change_state; if (!cw_run_state_machine(conn, &timer)){ cw_dbg(DBG_INFO,"WTP died"); wtpman_remove(wtpman); return NULL; }; /* switch (conn->capwap_transition){ case CW_TRANSITION(CAPWAP_STATE_DTLS_SETUP, CAPWAP_STATE_JOIN): { wait_join = cw_ktv_get_word(conn->global_cfg,"wait-join",CAPWAP_WAIT_JOIN); timer = cw_timer_start(wait_join); break; } case CW_TRANSITION(CAPWAP_STATE_JOIN, CAPWAP_STATE_JOIN): { char wtpname[CAPWAP_MAX_WTP_NAME_LEN]; cw_KTV_t * result; result = cw_ktv_get(conn->remote_cfg,"wtp-name",NULL); result->type->to_str(result,wtpname,CAPWAP_MAX_WTP_NAME_LEN); cw_dbg(DBG_INFO, "WTP joined: '%s', IP %s.", wtpname, sock_addr2str(&conn->addr,sock_buf) ); break; } case CW_TRANSITION(CAPWAP_STATE_JOIN,CAPWAP_STATE_TIMEOUT): { cw_dbg(DBG_MSG_ERR, "No join request from %s after %d seconds, WTP died.", sock_addr2str(&wtpman->conn->addr,sock_buf), wait_join); wtpman_remove(wtpman); return NULL; break; } case CW_TRANSITION(CAPWAP_STATE_JOIN, CAPWAP_STATE_CONFIGURE): { wait_change_state = cw_ktv_get_word(conn->global_cfg, "capwap-timers/change-state-pending-timer", CAPWAP_TIMER_CHANGE_STATE_PENDING_TIMER); break; } case CW_TRANSITION(CAPWAP_STATE_CONFIGURE,CAPWAP_STATE_TIMEOUT): { cw_dbg(DBG_MSG_ERR, "No Change State Event Request %s after %d seconds, WTP died.", sock_addr2str(&wtpman->conn->addr,sock_buf), wait_change_state); wtpman_remove(wtpman); return NULL; break; } } */ while (!cw_timer_timeout(timer)) { if (conn->update_cfg != NULL){ mavl_t tmp; tmp = conn->local_cfg; mavl_merge(conn->default_cfg, conn->local_cfg); mavl_merge(conn->default_cfg, conn->remote_cfg); conn->local_cfg=conn->update_cfg; cw_dbg(DBG_INFO, "Updating WTP %s",sock_addr2str(&conn->addr,sock_buf)); rc = cw_send_request(conn, CAPWAP_MSG_CONFIGURATION_UPDATE_REQUEST); conn->update_cfg=NULL; conn->local_cfg=tmp; } rc = cw_read_messages(wtpman->conn); if (rc < 0) { if (errno == EAGAIN) continue; } break; } if(rc<0){ conn->capwap_prevstate = conn->capwap_state; conn->capwap_state = CAPWAP_STATE_TIMEOUT; } } /* dtls is established, goto join state */ conn->capwap_state = CAPWAP_STATE_JOIN; if (!wtpman_join(wtpman)) { wtpman_remove(wtpman); return NULL; } cw_dbg(DBG_INFO, "WTP from %s has joined with session id: %s", sock_addr2str_p(&conn->addr,sock_buf), format_bin2hex(conn->session_id,16)); exit(0); /* // 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 a configuration status request. Nothing else. */ rc = 0; while (!cw_timer_timeout(timer) && wtpman->conn->capwap_state == CAPWAP_STATE_CONFIGURE) { rc = cw_read_messages(wtpman->conn); if (rc < 0) { if (errno != EAGAIN) break; } } cw_dbg_ktv_dump(conn->remote_cfg,DBG_INFO,"-------------dump------------","DMP","---------end dump --------"); if (!cw_result_is_ok(rc)) { cw_dbg(DBG_INFO, "WTP Problem: %s", cw_strrc(rc)); wtpman_remove(wtpman); return NULL; } if (conn->capwap_state == CW_STATE_IMAGE_DATA) { wtpman_image_data(wtpman); return NULL; } conn->capwap_state = CAPWAP_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 == CAPWAP_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,sock_buf)); break; } /* // mavl_del_all(conn->outgoing); // conn_clear_upd(conn,1); // props_to_sql(conn,conn->incomming,0); // radios_to_sql(conn); */ r = db_get_update_tasks(conn, sock_addr2str(&conn->addr,sock_buf)); if (r) { /* // if (!conn->outgoing->count) // continue; */ cw_dbg(DBG_INFO, "Updating WTP %s",sock_addr2str(&conn->addr,sock_buf)); rc = cw_send_request(conn, CAPWAP_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,sock_buf)); if (r) { /* // if (!conn->radios_upd->count) // continue; */ cw_dbg(DBG_INFO, "Updating Radios for %s",sock_addr2str(&conn->addr,sock_buf)); rc = cw_send_request(conn, CAPWAP_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,sock_buf), ""); wtpman_remove(wtpman); return NULL; }
/** * Format a Packet Header */ int cw_format_pkt_hdr(char *dst,int level,struct conn *conn, uint8_t * packet, int len,struct sockaddr *from) { char *s=dst; switch (level) { case DBG_PKT_IN: if (cw_get_hdr_flag_f(packet)){ s+=sprintf(s,"Fragment from %s",sock_addr2str_p(from)); } else{ s+=sprintf(s,"From %s",sock_addr2str_p(from)); } break; case DBG_PKT_OUT: if (cw_get_hdr_flag_f(packet)){ s+=sprintf(s,"Fragment to %s",sock_addr2str(from)); } else{ s+=sprintf(s,"To %s",sock_addr2str(from)); } break; } s+=sprintf(s," l=%d: ",len); int preamble = cw_get_hdr_preamble(packet); if (preamble==01){ s+=sprintf(s," (encrypted)"); return s-dst; } if (len<4) goto abort; /* if (cw_get_hdr_flag_f(packet)){ s+=sprintf(s," (fragmented)"); } */ int hlen = cw_get_hdr_hlen(packet); int rid = cw_get_hdr_rid(packet); int wbid = cw_get_hdr_wbid(packet); s+=sprintf(s," H:%d R:%02d W:%02d",hlen,rid,wbid); s+=sprintf(s," Flgs:"); s+=format_hdr_flags(s,packet); if (len<8) goto abort; int frag_id = cw_get_hdr_fragid(packet); int frag_offs = cw_get_hdr_fragoffset(packet); s+=sprintf(s," Frag/Offs:%d/%d",frag_id,frag_offs); if (cw_get_hdr_flag_m(packet)) { /* rmac is present, print the rmac */ int rmac_len=cw_get_hdr_rmac_len(packet); int plen=rmac_len; if (rmac_len+8>len) plen=len-8; if (rmac_len>10) plen=10; s+=sprintf(s," R-MAC:"); s+=format_mac(s,cw_get_hdr_rmac_data(packet),plen); if (rmac_len>10){ s+=sprintf(s," ... (len=%d)",rmac_len); } } if (cw_get_hdr_flag_w(packet)){ /* print wireless specific info */ int ws_len = cw_get_hdr_ws_len(packet); int plen = ws_len > 20 ? 20:ws_len; s+=sprintf(s," WS:"); s+=format_hexu(s,cw_get_hdr_ws_data(packet),plen); if (ws_len>20){ s+=sprintf(s," ... (len=%d)",ws_len); } } return s-dst; abort: s+=sprintf(s," Incomplete..."); return s-dst; }
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; }