void cw_dbg_msg(int level,struct conn *conn, uint8_t * packet, int len,struct sockaddr *from) { if (!cw_dbg_is_level(level)) return; char buf[1024]; char *s = buf; uint8_t * msgptr = cw_get_hdr_msg_ptr(packet); // int pplen = len - (msgptr-packet); int msg_id=cw_get_msg_id(msgptr); s+=sprintf(s,"%s Message (type=%d) ",cw_strmsg(msg_id),msg_id); if ( level == DBG_MSG_IN ) s+=sprintf(s,"from %s ",sock_addr2str(from)); else s+=sprintf(s,"to %s ",sock_addr2str(from)); s+=sprintf(s,", Seqnum: %d ElemLen: %d",cw_get_msg_seqnum(msgptr),cw_get_msg_elems_len(msgptr)); //abort: cw_dbg(level,"%s",buf); }
int netconn_process_packet(struct netconn *nc, uint8_t * packet, int len, struct sockaddr *from) { char sock_buf[SOCK_ADDR_BUFSIZE]; /*// cw_dbg_pkt_nc(DBG_PKT_IN, nc, packet, len, from);*/ if (len < 8) { /* packet too short */ cw_dbg(DBG_PKT_ERR, "Discarding packet from %s, packet too short, len=%d, at least 8 expected.", sock_addr2str(&nc->addr,sock_buf), len); errno = EAGAIN; return -1; } int preamble = cw_get_hdr_preamble(packet); if ((preamble & 0xf0) != (CAPWAP_VERSION << 4)) { /* wrong version */ cw_dbg(DBG_PKT_ERR, "Discarding packet from %s, wrong version, version=%d, version %d expected.", sock_addr2str(&nc->addr,sock_buf), (preamble & 0xf0) >> 4, CAPWAP_VERSION); errno = EAGAIN; return -1; }
static void wtpman_image_data(struct wtpman *wtpman) { struct conn *conn = wtpman->conn; /* Image upload */ const char *filename = mbag_get_str(conn->outgoing, CW_ITEM_IMAGE_FILENAME, NULL); if (!filename) { cw_log(LOG_ERR, "Can't send image to %s. No Image Filename Item found.", sock_addr2str(&conn->addr)); return; } cw_dbg(DBG_INFO, "Sending image file '%s' to '%s'.", filename, sock_addr2str(&conn->addr)); FILE *infile = fopen(filename, "rb"); if (infile == NULL) { cw_log(LOG_ERR, "Can't open image %s: %s", sock_addr2str(&conn->addr), strerror(errno)); return; } CW_CLOCK_DEFINE(clk); cw_clock_start(&clk); mbag_item_t *eof = mbag_set_const_ptr(conn->outgoing, CW_ITEM_IMAGE_FILEHANDLE, infile); int rc = 0; while (conn->capwap_state == CW_STATE_IMAGE_DATA && rc == 0 && eof != NULL) { rc = cw_send_request(conn, CW_MSG_IMAGE_DATA_REQUEST); eof = mbag_get(conn->outgoing, CW_ITEM_IMAGE_FILEHANDLE); } if (rc) { cw_log(LOG_ERR, "Error sending image to %s: %s", sock_addr2str(&conn->addr), cw_strrc(rc)); } else { cw_dbg(DBG_INFO, "Image '%s' sucessful sent to %s in %0.1f seconds.", filename, sock_addr2str(&conn->addr), cw_clock_stop(&clk)); conn->capwap_state = CW_STATE_NONE; } fclose(infile); wtpman_remove(wtpman); }
static int wtpman_join(void *arg, time_t timer) { struct wtpman *wtpman = (struct wtpman *) arg; struct conn *conn = wtpman->conn; wtpman->conn->outgoing = mbag_create(); wtpman->conn->incomming = mbag_create(); conn->config = conn->incomming; // wtpman->conn->local = ac_config; mbag_set_str(conn->local, CW_ITEM_AC_NAME, conf_acname); wtpman->conn->capwap_state = CW_STATE_JOIN; // wtpman->conn->actions = &capwap_actions; // wtpman->conn->itemstore = mbag_create(); cw_dbg(DBG_INFO, "Join State - %s", sock_addr2str(&conn->addr)); int rc; while (!cw_timer_timeout(timer) && wtpman->conn->capwap_state == CW_STATE_JOIN) { rc = cw_read_messages(wtpman->conn); if (rc < 0) { break; } } if (rc != 0) { cw_log(LOG_ERR, "Error joining WTP %s", cw_strerror(rc)); return 0; } if (wtpman->conn->capwap_state == CW_STATE_JOIN) { cw_dbg(DBG_MSG_ERR, "No join request from %s after %d seconds, WTP died.", sock_addr2str(&wtpman->conn->addr), wtpman->conn->wait_dtls); return 0; } return 1; }
int cw_in_check_disc_req(struct conn *conn, struct cw_action_in *a, uint8_t * data, int len,struct sockaddr *from) { cw_action_in_t *mlist[120]; int n = cw_check_missing_mand(mlist, conn, a); conn->capwap_state = CW_STATE_NONE; if (n && conn->strict_capwap) { cw_dbg_missing_mand(DBG_MSG_ERR, conn, mlist, n, a); /* if mandatory elements are missing, in strict mode send no discovery response */ cw_dbg(DBG_MSG_ERR, "Ignoring Discovery Request from %s - missing mandatory elements.", sock_addr2str(from)); return -1; } if ( n ) { /* put a warning here */ cw_dbg_missing_mand(DBG_RFC, conn, mlist, n, a); } /* ok, send response */ conn->capwap_state = CW_STATE_JOIN; return 0; }
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; }
void cwsend_change_state_event_response(struct conn * conn,int seqnum, struct radioinfo * radioinfo) { cw_dbg(DBG_CW_MSG,"Sending change state response to %s, seq = %d",sock_addr2str(&conn->addr),seqnum); struct cwmsg * cwmsg = &conn->resp_msg; cwmsg_init(cwmsg,conn->resp_buffer,CWMSG_CHANGE_STATE_EVENT_RESPONSE,seqnum,NULL); cwmsg_addelem_result_code(cwmsg,0); cwmsg_addelem_radio_operational_state(cwmsg,radioinfo); conn_send_response(conn,cwmsg,seqnum); }
void props_to_sql(struct conn *conn, mbag_t mb, const char *mid) { // XXX for the now we use just the IP adress as ID char *wtp_id = sock_addr2str(&conn->addr); // cw_dbg(DBG_X, "WTPID: %s\n", wtp_id); MAVLITER_DEFINE(it, mb); mavliter_foreach(&it) { mbag_item_t *i = mavliter_get(&it); const struct cw_itemdef *cwi; if (!mid){ cwi = cw_itemdef_get(conn->actions->items, i->id, NULL); } else{ cwi = cw_itemdef_get(conn->actions->items, mid,i->id); } if (!cwi){ cw_dbg(DBG_WARN,"No definition for item %s found.",i->id); continue; } if (i->type==MBAG_MBAG){ if (mid){ cw_log(LOG_ERROR,"Depth for %s",i->id); continue; } props_to_sql(conn,i->data,i->id); continue; } DBGX("SQL ID %s,%s", i->id, cwi->id); DBGX("SQL Type %s,Typecwd %s", i->type->name, cwi->type->name); // printf("%s != %s ?\n",i->type->name,cwi->type->name); char str[256]; if (i->type->to_str) { i->type->to_str(i, str); db_put_wtp_prop(wtp_id, cwi->id, cwi->sub_id, str); } else { cw_log(LOG_ERR, "Can't converto to str for %s", cwi->id, cwi->sub_id); } } }
void radios_to_sql(struct conn *conn) { char *wtp_id = sock_addr2str(&conn->addr); MAVLITER_DEFINE(it, conn->radios); mavliter_foreach(&it) { struct mbag_item * i = mavliter_get(&it); int rid = i->iid; radio_to_sql(conn,wtp_id,rid,i->data); } }
static int to_str ( const struct cw_KTV *data, char *dst, int max_len ) { int l; struct sockaddr_storage addr; l = bstr_len(data->val.ptr); if (l==4){ addr.ss_family = AF_INET; memcpy(&(((struct sockaddr_in*)&addr)->sin_addr),bstr_data(data->val.ptr),4); sock_addr2str(&addr,dst); return 4; } if (l==16){ addr.ss_family = AF_INET6; memcpy(&(((struct sockaddr_in6*)&addr)->sin6_addr),bstr_data(data->val.ptr),16); sock_addr2str(&addr,dst); return 16; } *dst=0; return 0; }
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 wtpconf_ac_list() { if (conf_ac_list) return 1; int i; int len=0; int bcrc; struct sockaddr_storage bcaddr; bcrc = sock_getifaddr(conf_primary_if,AF_INET,IFF_BROADCAST,(struct sockaddr*)&bcaddr); if (bcrc) len++; int deflen = sizeof(default_ac_list)/sizeof(char*); len += deflen; conf_ac_list = malloc(len*sizeof(char*)); if (!conf_ac_list) return 0; for (i=0; i<deflen; i++){ conf_ac_list[i]=strdup(default_ac_list[i]); if (!conf_ac_list[i]) return 0; } if (bcrc){ // char bcstr[100]; char *bcstr; // sock_addrtostr((struct sockaddr*)&bcaddr,bcstr,100); bcstr = sock_addr2str((struct sockaddr*)&bcaddr); // char * c = strchr(bcstr,':'); // *c=0; conf_ac_list[i]=strdup(bcstr); } conf_ac_list_len=len; #ifdef WITH_CW_LOG_DEBUG for (i=0; i<conf_ac_list_len; i++){ cw_dbg(DBG_INFO,"Using AC: %s",conf_ac_list[i]); } #endif return 1; }
void cwmsg_addelem_vendor_cisco_mwar_addr(struct cwmsg *msg, struct conn *conn) { uint8_t data [7]; switch (((struct sockaddr*)&conn->addr)->sa_family) { case AF_INET: { data[0]=2; /* mwar type */ data[5]=0; data[6]=0; printf("Adding mwar addr %s\n",sock_addr2str(&conn->addr)); struct sockaddr_in * sain = (struct sockaddr_in*)&conn->addr; memcpy(data+1,(uint8_t*)&sain->sin_addr,4); cwmsg_addelem_vendor_specific_payload(msg, CW_VENDOR_ID_CISCO, CW_CISCO_MWAR_ADDR, data,7); break; } /* case AF_INET6: { int id; if (cw_mode == CWMODE_CISCO) id = CWMSGELEM_WTP_IPV6_IP_ADDR; else id = CWMSGELEM_CAPWAP_LOCAL_IPV6_ADDRESS; struct sockaddr_in6 * sain = (struct sockaddr_in6*)&a; return cwmsg_addelem(msg,id,(uint8_t*)&sain->sin6_addr,16); } break; */ } }
void onaccept_proc(void* userptr, SOCK_HANDLE sock, const SOCK_ADDR* pname) { char addr[50]; NETWORK_EVENT event; printf("accept from %s\n", sock_addr2str(pname, addr)); sock_nonblock(sock); event.OnConnect = onconnect_proc; event.OnData = ondata_proc; event.OnDisconnect = ondisconnect_proc; event.recvbuf_pool = recvbuf_pool; event.recvbuf_buf = NULL; event.recvbuf_max = recvbuf_size; if(!network_add(sock, &event, NULL)) { sock_disconnect(sock); sock_close(sock); } }
void ondata_proc(NETWORK_HANDLE handle, void* userptr) { unsigned int count; NETWORK_DOWNBUF* bufs[10]; char addr[50]; sock_addr2str(network_get_peername(handle), addr); printf("%p ondata(%d).\n", handle, network_recvbuf_len(handle)); count = network_downbufs_alloc(bufs, sizeof(bufs)/sizeof(bufs[0]), network_recvbuf_len(handle)); if(count>0) { const void* buf; buf = network_recvbuf_ptr(handle, 0, network_recvbuf_len(handle)); if(buf) { network_downbufs_fill(bufs, count, 0, buf, network_recvbuf_len(handle)); network_send(handle, bufs, count); } } network_recvbuf_commit(handle, network_recvbuf_len(handle)); }
void config_to_sql(struct conn *conn) { // XXX for the moment we use just the IP adress as ID char *wtp_id = sock_addr2str(&conn->addr); // cw_dbg(DBG_X, "WTPID: %s\n", wtp_id); MAVLITER_DEFINE(it, conn->incomming); mavliter_foreach(&it) { mbag_item_t *i = mavliter_get(&it); const struct cw_itemdef *cwi = cw_itemdef_get(conn->actions->items, i->id, NULL); cw_dbg(DBG_X,"ID GOT: %s",i->id); if (cwi) { DBGX("SQL ID %s,%s", i->id, cwi->id); DBGX("SQL Type %s,Typecwd %s", i->type->name, cwi->type->name); // printf("%s != %s ?\n",i->type->name,cwi->type->name); char str[256]; if (i->type->to_str) { i->type->to_str(i, str); db_put_wtp_prop(wtp_id, cwi->id, cwi->sub_id, str); } else { cw_log(LOG_ERR, "Can't converto to str for %s", cwi->id, cwi->sub_id); } } else { // DBGX("ID %d",i->id); } } }
void conn_q_add_packet(struct conn * conn,uint8_t *packet,int len) { int qwpos = conn->qwpos; if (qwpos==conn->qsize) qwpos=0; if (conn->qrpos==qwpos){ /* no buffers, discard packet */ cw_dbg(DBG_PKT_ERR, "Discarding packet from %s, no queue buffers left", sock_addr2str(&conn->addr)); return; } conn->q[qwpos]=malloc(len+4); if (conn->q[qwpos]==NULL) return; *((uint32_t*)(conn->q[qwpos]))=len; memcpy(conn->q[qwpos]+4,packet,len); conn->qwpos=qwpos+1; sem_post(&conn->q_sem); }
void netconn_q_add_packet(struct netconn * nc,uint8_t *packet,int len) { char sock_buf[SOCK_ADDR_BUFSIZE]; int qwpos = nc->qwpos; if (qwpos==nc->qsize) qwpos=0; if (nc->qrpos==qwpos){ /* no buffers, discard packet */ cw_dbg(DBG_PKT_ERR, "Discarding packet from %s, no queue buffers left", sock_addr2str(&nc->addr,sock_buf)); return; } nc->q[qwpos]=malloc(len+4); if (nc->q[qwpos]==NULL) return; *((uint32_t*)(nc->q[qwpos]))=len; memcpy(nc->q[qwpos]+4,packet,len); nc->qwpos=qwpos+1; sem_post(&nc->q_sem); }
static int process_elements(struct conn *conn, uint8_t * rawmsg, int len, struct sockaddr *from) { struct cw_action_in as, *af, *afm; int offset = cw_get_hdr_msg_offset(rawmsg); uint8_t *msg_ptr = rawmsg + offset; int elems_len = cw_get_msg_elems_len(msg_ptr); int payloadlen = len - offset; /* pre-check message */ if (payloadlen - 8 != elems_len) { if (conn->strict_hdr) { cw_dbg(DBG_MSG_ERR, "Discarding message from %s, msgelems len=%d, payload len=%d, (Strict CAPWAP) ", sock_addr2str(&conn->addr), elems_len, payloadlen - 8); errno = EAGAIN; return -1; } if (elems_len < payloadlen - 8) { cw_dbg(DBG_RFC, "Packet from from %s has %d bytes of extra data, ignoring.", sock_addr2str(&conn->addr), payloadlen - 8 - elems_len); elems_len = len - 8; } if (elems_len > payloadlen - 8) { cw_dbg(DBG_RFC, "Packet from from %s has msgelems len of %d bytes, but has only %d bytes of data, truncating.", sock_addr2str(&conn->addr), elems_len, payloadlen - 8); elems_len = payloadlen - 8; } } if (!conn->detected) { //struct mod_ac *mod; struct cw_actiondef *ad = load_mods(conn, rawmsg, len, elems_len, from); if (!ad) { cw_log(LOG_ERR, "Error"); errno = EAGAIN; return -1; } conn->actions = ad; conn->detected = 1; } /* prepare struct for search operation */ as.capwap_state = conn->capwap_state; as.msg_id = cw_get_msg_id(msg_ptr); as.vendor_id = 0; as.elem_id = 0; as.proto = 0; /* Search for state/message combination */ afm = cw_actionlist_in_get(conn->actions->in, &as); if (!afm) { /* Throw away unexpected response messages */ if (!(as.msg_id & 1)) { cw_dbg(DBG_MSG_ERR, "Message type %d (%s) unexpected/illegal in %s State, discarding.", as.msg_id, cw_strmsg(as.msg_id), cw_strstate(conn->capwap_state)); errno = EAGAIN; return -1; } /* Request message not found in current state, check if we know anything else about this message type */ const char *str = cw_strheap_get(conn->actions->strmsg, as.msg_id); int result_code = 0; if (str) { /* Message found, but it was in wrong state */ cw_dbg(DBG_MSG_ERR, "Message type %d (%s) not allowed in %s State.", as.msg_id, cw_strmsg(as.msg_id), cw_strstate(as.capwap_state)); result_code = CW_RESULT_MSG_INVALID_IN_CURRENT_STATE; } else { /* Message is unknown */ cw_dbg(DBG_MSG_ERR, "Message type %d (%s) unknown.", as.msg_id, cw_strmsg(as.msg_id), cw_strstate(as.capwap_state)); result_code = CW_RESULT_MSG_UNRECOGNIZED; } cw_send_error_response(conn, rawmsg, result_code); errno = EAGAIN; return -1; } if (conn->msg_start){ conn->msg_start(conn, afm, rawmsg, len, from); } /* Execute start processor for message */ if (afm->start) { afm->start(conn, afm, rawmsg, len, from); } uint8_t *elems_ptr = cw_get_msg_elems_ptr(msg_ptr); uint8_t *elem; /* Create an avltree to catch the found mandatory elements */ conn->mand = stravltree_create(); int unrecognized = 0; /* iterate through message elements */ cw_foreach_elem(elem, elems_ptr, elems_len) { as.elem_id = cw_get_elem_id(elem); int elem_len = cw_get_elem_len(elem); af = cw_actionlist_in_get(conn->actions->in, &as); if (!af) { unrecognized++; cw_dbg(DBG_ELEM_ERR, "Element %d (%s) not allowed in msg of type %d (%s), ignoring.", as.elem_id, cw_strelemp(conn->actions, as.elem_id), as.msg_id, cw_strmsg(as.msg_id)); continue; } if (!check_len(conn, af, cw_get_elem_data(elem), elem_len, from)) { continue; } cw_dbg_elem(DBG_ELEM, conn, as.msg_id, as.elem_id, cw_get_elem_data(elem), elem_len); int afrc = 1; if (af->start) { afrc = af->start(conn, af, cw_get_elem_data(elem), elem_len, from); } if (af->mand && afrc) { /* add found mandatory message element to mand list */ stravltree_add(conn->mand, af->item_id); } if(conn->elem_end){ afrc = conn->elem_end(conn,af,afrc,cw_get_elem_data(elem), elem_len,from); } }
/** * Run discovery for on address (eg broadcast 255.255.255.255) */ static int cw_run_discovery(struct conn *conn, const char *acaddr) { /* get addr of destination */ struct addrinfo hints; struct addrinfo *res, *res0; memset(&hints, 0, sizeof(hints)); hints.ai_socktype = SOCK_DGRAM; hints.ai_family = PF_UNSPEC; int rc = getaddrinfo(acaddr, conf_control_port, &hints, &res0); if (rc) { cw_log(LOG_ERR, "Can't connect to AC %s: %s", acaddr, gai_strerror(rc)); return 0; } for (res = res0; res; res = res->ai_next) { int sockfd; int opt; sockfd = socket(res->ai_family, SOCK_DGRAM, 0); if (sockfd == -1) { cw_log(LOG_ERR, "Can't create socket for %s: %s", acaddr, strerror(errno)); continue; } opt = 1; if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &opt, sizeof(opt)) < 0) { cw_log(LOG_ERR, "Can't set broadcast sockopt"); } sock_set_recvtimeout(sockfd, 1); sock_set_dontfrag(sockfd, 0); sock_copyaddr(&conn->addr, res->ai_addr); if (conf_ip){ struct sockaddr bind_address; sock_strtoaddr(conf_ip,&bind_address); int brc = bind(sockfd,&bind_address,sock_addrlen(&bind_address)); if (brc<0) { cw_log(LOG_ERR,"Can't bind to %s",sock_addr2str(&bind_address)); return 0; } } conn->sock = sockfd; conn->readfrom = conn_recvfrom_packet; run_discovery(conn); conn->readfrom=NULL; close(sockfd); } freeaddrinfo(res0); return 0; }
int wtpinfo_print(char *str, struct wtpinfo * wtpinfo) { char hstr[64]; char *s = str; s+=sprintf (s,"\tWTP Name: %s\n", (!wtpinfo->name ? (uint8_t*)"Not set" : wtpinfo->name) ); s+=sprintf (s,"\tLocation: %s\n", (!wtpinfo->location ? (uint8_t*)"Not set" : wtpinfo->location) ); s+=sprintf (s,"\tMAC Adress: "); if (wtpinfo->macaddress){ sock_hwaddrtostr(wtpinfo->macaddress,wtpinfo->macaddress_len,hstr,":"); s+=sprintf(s,"%s\n",hstr); } else s+=sprintf(s,"Not set\n"); char disctypestr[32]; switch(wtpinfo->discovery_type){ case CW_DISCOVERY_TYPE_STATIC: sprintf(disctypestr,"Static"); break; case CW_DISCOVERY_TYPE_DHCP: sprintf(disctypestr,"DHCP"); break; case CW_DISCOVERY_TYPE_DNS: sprintf(disctypestr,"DNS"); break; case CW_DISCOVERY_TYPE_AC_REFERRAL: sprintf(disctypestr,"AC Referral"); break; default: sprintf(disctypestr,"Unknown"); break; } s+=sprintf (s,"\tDiscovery Type: %s\n",disctypestr); // sock_addrtostr((struct sockaddr*)&wtpinfo->local_ip,hstr,64); /* int i0; for (i0=0; i0<10; i0++){ printf("%d\n", ((char*)(&wtpinfo->local_ip))[i0] ); } */ s+=sprintf (s,"\tLocal IP: %s\n",sock_addr2str(&(wtpinfo->local_ip))); s+=sprintf (s,"\tVendor ID: %d, %s\n", wtpinfo->vendor_id,lw_vendor_id_to_str(wtpinfo->vendor_id) ); s+=sprintf (s,"\tModel No.: "); //, (!wtpinfo->model_no ? (uint8_t*)"Not set" : wtpinfo->model_no) ); s+=bstr_to_str(s,wtpinfo->model_no,0); s+=sprintf(s,"\n"); // s+=sprintf (s,"\tSerial No.: %s\n", (!wtpinfo->serial_no ? (uint8_t*)"Not set" : wtpinfo->serial_no) ); s+=sprintf (s,"\tSerial No.: "); s+=bstr_to_str(s,wtpinfo->serial_no,0); s+=sprintf(s,"\n"); s+=sprintf (s,"\tBoard ID: "); s+=bstr_to_str(s,wtpinfo->board_id,0); s+=sprintf(s,"\n"); s+=sprintf (s,"\tBoard Revision: "); s+=bstr_to_str(s,wtpinfo->board_revision,0); s+=sprintf(s,"\n"); // s+=sprintf (s,"\tBoard Id: %s\n", (!wtpinfo->board_id ? (uint8_t*)"Not set" : wtpinfo->board_id) ); s+=sprintf (s,"\tSoftware Version: "); // s+=version_print(s,wtpinfo->software_version,wtpinfo->software_version_len,wtpinfo->software_vendor_id); s+=cw_format_version(s,wtpinfo->software_version,wtpinfo->software_vendor_id,"Not set"); s+=sprintf (s,"\n"); s+=sprintf (s,"\tHardware Version: "); s+=version_print(s,wtpinfo->hardware_version,wtpinfo->hardware_version_len,wtpinfo->hardware_vendor_id); s+=sprintf (s,"\tBootloader Version: "); s+=version_print(s,wtpinfo->bootloader_version,wtpinfo->bootloader_version_len,wtpinfo->bootloader_vendor_id); //, (!wtpinfo->software_version ? (uint8_t*)"Not set" : wtpinfo->software_version) ); // s+=sprintf (s,"\tHardware Version: %s\n", (!wtpinfo->hardware_version ? (uint8_t*)"Not set" : wtpinfo->hardware_version) ); s+=sprintf (s,"\tMax Radios: %d\n",wtpinfo->max_radios); s+=sprintf (s,"\tRadios in use: %d\n",wtpinfo->radios_in_use); s+=sprintf (s,"\tSession ID: "); if (wtpinfo->session_id) { int i; for (i=0; i<bstr_len(wtpinfo->session_id); i++) s+=sprintf(s,"%02X",bstr_data(wtpinfo->session_id)[i]); } else s+=sprintf(s,"Not set"); s+=sprintf(s,"\n"); s+=sprintf (s,"\tMAC Type: "); switch (wtpinfo->mac_type){ case WTP_MAC_TYPE_LOCAL: s+=sprintf(s,"local"); break; case WTP_MAC_TYPE_SPLIT: s+=sprintf(s,"split"); break; case WTP_MAC_TYPE_BOTH: s+=sprintf(s,"local, split"); break; } s+=sprintf(s,"\n"); s+=sprintf (s,"\tFrame Tunnel Mode: "); s+=sprintf(s,"(%08X)",wtpinfo->frame_tunnel_mode); char * c=""; if (wtpinfo->frame_tunnel_mode & WTP_FRAME_TUNNEL_MODE_N){ s+=printf (s,"%snative",c);c=", "; } if (wtpinfo->frame_tunnel_mode & WTP_FRAME_TUNNEL_MODE_E){ s+=sprintf (s,"%s802.3",c);c=", "; } if (wtpinfo->frame_tunnel_mode & WTP_FRAME_TUNNEL_MODE_L){ s+=sprintf (s,"%sLocal bridging",c);c=", "; } if (wtpinfo->frame_tunnel_mode == 0) s+=sprintf(s," None"); s+=sprintf(s,"\n"); s+=sprintf(s,"\tRadios: %d\n",wtpinfo->max_radios); int i; char ristr[2048]; char *r = ristr; for (i=0; i<wtpinfo->max_radios; i++){ if (wtpinfo->radioinfo[i].set) r+=radioinfo_print(r,&wtpinfo->radioinfo[i]); } s+=sprintf(s,"%s",ristr); s+=sprintf(s,"Encryption: %08x\n",wtpinfo->encryption_cap); s+=wtp_reboot_statistics_print(s,&wtpinfo->reboot_statistics); return s-str; }
int join(struct sockaddr *sa) { int sockfd; int rc; sockfd = socket(AF_INET,SOCK_DGRAM,0); if (sockfd==-1){ cw_log(LOG_ERR,"Can't create socket: %s\n",strerror(errno)); return -1; } sock_set_recvtimeout(sockfd,1); rc = connect(sockfd,(struct sockaddr*)sa,sock_addrlen((struct sockaddr*)sa)); if (rc<0){ char str[100]; sock_addrtostr(sa,str,100); cw_log(LOG_ERR,"Can't connect to %s: %s\n",str,strerror(errno)); close(sockfd); return -1; } struct conn * conn = get_conn(); conn->sock=sockfd; sock_copyaddr(&conn->addr,sa); #ifdef WITH_DTLS cw_dbg (DBG_DTLS,"Establishing DTLS session with %s",sock_addr2str(sa)); /* #ifdef WITH_CW_LOG_DEBUG { char str[100]; sock_addrtostr(sa,str,100); cw_log_debug0("Establishing DTLS connection to %s",str); } #endif */ if (conf_dtls_psk){ conn->dtls_psk=conf_dtls_psk; conn->dtls_psk_len=strlen(conn->dtls_psk); conn->dtls_cipher=conf_dtls_cipher; } if (conf_sslkeyfilename && conf_sslcertfilename){ conn->dtls_key_file = conf_sslkeyfilename; conn->dtls_cert_file = conf_sslcertfilename; conn->dtls_key_pass = conf_sslkeypass; conn->dtls_cipher=conf_dtls_cipher; } rc = dtls_connect(conn); if (rc!=1){ dtls_shutdown(conn); char str[100]; sock_addrtostr(sa,str,100); cw_log(LOG_ERR,"Cant establish DTLS connection to %s",str); close(sockfd); return 0; } #endif cw_dbg (DBG_DTLS,"DTLS session established with %s, cipher=%s",sock_addr2str(sa),dtls_get_cipher(conn)); exit(0); #ifdef WITH_CW_LOG_DEBUG { char str[100]; sock_addrtostr(sa,str,100); cw_log_debug0("DTLS connection to %s established",str); } #endif join_state(conn); 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; }
struct wtpman *wtpman_create(int socklistindex, struct sockaddr *srcaddr, int dtlsmode) { struct sockaddr dbgaddr; socklen_t dbgaddrl; int sockfd, replyfd; char sock_buf[SOCK_ADDR_BUFSIZE]; struct wtpman *wtpman; wtpman = malloc(sizeof(struct wtpman)); if (!wtpman) return 0; memset(wtpman, 0, sizeof(struct wtpman)); if (socklist[socklistindex].type != SOCKLIST_UNICAST_SOCKET) { int port = sock_getport(&socklist[socklistindex].addr); replyfd = socklist_find_reply_socket(srcaddr, port); if (replyfd == -1) { cw_log(LOG_ERR, "Can't find reply socket for request from %s", sock_addr2str(srcaddr,sock_buf)); free(wtpman); return NULL; } } else { replyfd = socklist[socklistindex].sockfd; } sockfd = replyfd; /*//socklist[socklistindex].reply_sockfd;*/ dbgaddrl = sizeof(dbgaddr); getsockname(sockfd, &dbgaddr, &dbgaddrl); cw_dbg(DBG_INFO, "Creating wtpman on socket %d, %s:%d", sockfd, sock_addr2str(&dbgaddr,sock_buf), sock_getport(&dbgaddr)); wtpman->conn = conn_create(sockfd, srcaddr, 100); wtpman->conn->role = CW_ROLE_AC; wtpman->conn->data_sock = socklist[socklistindex].data_sockfd; sock_copyaddr(&wtpman->conn->data_addr, (struct sockaddr *) &wtpman->conn->addr); if (!wtpman->conn) { wtpman_destroy(wtpman); return NULL; } wtpman->conn->mods = conf_mods; wtpman->conn->strict_capwap = conf_strict_capwap; wtpman->conn->strict_hdr = conf_strict_headers; /* // wtpman->conn->radios = mbag_i_create(); // wtpman->conn->radios_upd = mbag_i_create(); // wtpman->conn->local = ac_config; //wtpman->conn->capwap_mode=0; //CW_MODE_STD; //CISCO; // wtpman->conn->capwap_mode = CW_MODE_CISCO; //wtpman->conn->strict_capwap_hdr=0; */ wtpman->conn->local_cfg = cw_ktv_create(); wtpman->conn->global_cfg = actube_global_cfg; wtpman->conn->local_cfg = actube_global_cfg; /* when created caused by a packet in DTLS mode, we try * to find out the modules to load, for detected connection * from discovery request */ if (dtlsmode){ int rc; struct cw_Mod *cmod, *bmod; rc = discovery_cache_get(discovery_cache,srcaddr,&cmod,&bmod); if (rc){ cw_dbg(DBG_INFO, "Initializing with mod %s %s",cmod->name,bmod->name); wtpman->conn->msgset = cw_mod_get_msg_set(wtpman->conn,cmod,bmod); wtpman->conn->detected=1; cmod->setup_cfg(wtpman->conn); } } return wtpman; }
/** * Establish a DTLS connection using gnutls library * @see #dtls_connec */ int dtls_gnutls_connect(struct conn *conn) { int rc; char sock_buf[SOCK_ADDR_BUFSIZE]; struct dtls_gnutls_data *d; gnutls_datum_t key; d = dtls_gnutls_data_create(conn, GNUTLS_CLIENT | GNUTLS_DATAGRAM | GNUTLS_NONBLOCK); if (!d) return 0; /*// gnutls_dh_set_prime_bits(d->session, 512);*/ /*#if GNUTLS_VERSION_NUMBER >= 0x030100 gnutls_handshake_set_timeout(d->session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT); gnutls_dtls_set_data_mtu(d->session, 1500); #endif gnutls_dtls_set_mtu(d->session, 1500); */ /* if (conn->dtls_psk != NULL){ key.data=(unsigned char*)conn->dtls_psk; key.size=strlen(conn->dtls_psk); rc = gnutls_credentials_set(d->session, GNUTLS_CRD_PSK, &key); if (rc<0) { cw_log(LOG_ERR, "DTLS - Can't set x.509 credentials: %s", gnutls_strerror(rc)); dtls_gnutls_data_destroy(d); return 0; } } */ if (conn->dtls_psk_enable){ gnutls_psk_client_credentials_t cred; rc = gnutls_psk_allocate_client_credentials(&cred); if (rc != 0) { cw_dbg(DBG_DTLS,"gnutls_psk_allocate_client_credentials() failed.\n"); return 0; } key.size = bstr16_len(conn->dtls_psk); key.data = bstr16_data(conn->dtls_psk); /* Put the username and key into the structure we use to tell GnuTLs what // the credentials are. The example server doesn't care about usernames, so // we use "Alice" here.*/ rc = gnutls_psk_set_client_credentials(cred, "Alice", &key, GNUTLS_PSK_KEY_RAW); rc = gnutls_credentials_set(d->session, GNUTLS_CRD_PSK, cred); if (rc != 0) { cw_log(LOG_ERR,"gnutls_credentials_set() failed."); } } cw_dbg(DBG_DTLS,"Starting handshake"); do { rc = gnutls_handshake(d->session); } while (rc == GNUTLS_E_AGAIN); if (rc < 0) { cw_log(LOG_ERR, "DTLS (gnutls) Can't connect to %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_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; }
int socklist_add_unicast(const char *addr, const char *port, int ac_proto) { if (!socklist_check_size()) return 0; struct addrinfo hints; struct addrinfo *res, *res0; memset(&hints, 0, sizeof(hints)); hints.ai_socktype = SOCK_DGRAM; hints.ai_family = PF_UNSPEC; hints.ai_flags = AI_PASSIVE; int rc = getaddrinfo(addr, port, &hints, &res0); if (rc != 0) { cw_log(LOG_ERR, "Can't bind unicast address '%s': %s", addr, gai_strerror(rc)); return 0; } for (res = res0; res; res = res->ai_next) { char ifname[64]; struct sockaddr netmask; struct sockaddr broadcast; ifname[0] = 0; rc = sock_getifinfo(res->ai_addr, ifname, &broadcast, &netmask); if (!rc) { cw_log(LOG_ERR, "No interface found for %s, can't bind.", addr); continue; } /* Bind the control port */ struct sockaddr *sa = res->ai_addr; int sockfd = socket(res->ai_addr->sa_family, SOCK_DGRAM, 0); /* create socket */ if (sockfd == -1) { cw_log(LOG_ERR, "Can't create unicast socket: %s", strerror(errno)); continue; } /* bind address */ if (bind(sockfd, sa, sock_addrlen(sa)) < 0) { close(sockfd); cw_log(LOG_ERR, "Can't bind unicast socket %s: %s", addr, strerror(errno)); continue; } socklist[socklist_len].sockfd = sockfd; // socklist[socklist_len].reply_sockfd = sockfd; socklist[socklist_len].family = sa->sa_family; socklist[socklist_len].type = SOCKLIST_UNICAST_SOCKET; socklist[socklist_len].ac_proto = ac_proto; if (res->ai_addr->sa_family == AF_INET) { memcpy(&socklist[socklist_len].netmask, &netmask, sock_addrlen(&netmask)); memcpy(&socklist[socklist_len].addr, res->ai_addr, sock_addrlen(res->ai_addr)); cw_log(LOG_INFO, "Bound to: %s:%s (%i) on interface %s, netmask %s", addr, port, sockfd, ifname, sock_addr2str(&netmask)); } else { cw_log(LOG_INFO, "Bound to: [%s]:%s (%i) on interface %s", addr, port, sockfd, ifname); } /* Bind the data port */ sa = res->ai_addr; /* XXX data port is currently hard coded */ sock_setport(sa,5247); sockfd = socket(res->ai_addr->sa_family, SOCK_DGRAM, 0); /* create socket */ if (sockfd == -1) { cw_log(LOG_ERR, "Can't create unicast data socket: %s", strerror(errno)); continue; } /* bind address */ if (bind(sockfd, sa, sock_addrlen(sa)) < 0) { close(sockfd); cw_log(LOG_ERR, "Can't bind unicast data socket %s: %s", addr, strerror(errno)); continue; } cw_log(LOG_INFO, "Bound to data port: [%s]:%s (%i) on interface %s", addr, "5247", sockfd, ifname); socklist[socklist_len].data_sockfd = sockfd; socklist_len++; } freeaddrinfo(res0); return 1; }
void process_cw_ctrl_packet(int index,struct sockaddr * addr, uint8_t * buffer, int len) { int sock = socklist[index].reply_sockfd; char hdrstr[1024]; hdr_print(hdrstr,buffer,len); cw_log_debug2("Header for packet from %s\n%s",sock_addr2str(addr),hdrstr); /* first of all check preamble */ int preamble = CWTH_GET_PREAMBLE(buffer); #ifdef WITH_DTLS if (preamble != CAPWAP_PACKET_PREAMBLE && preamble != CAPWAP_DTLS_PACKET_PREAMBLE){ #else if (preamble != CAPWAP_PACKET_PREAMBLE ){ #endif cw_log_debug1("Discarding packet, wrong preamble, preamble = 0x%01X",preamble); return; } wtplist_lock(); struct wtpman * wtpman = wtplist_get(addr); if (!wtpman){ wtpman = wtpman_create(index,addr); if (!wtpman ){ cw_log(LOG_ERR,"Error creating wtpman: %s",strerror(errno)); wtplist_unlock(); return; } if (!wtplist_add(wtpman)){ cw_log(LOG_ERR,"Error adding wtpman: Too many wtp connections"); wtpman_destroy(wtpman); wtplist_unlock(); return; }; wtpman_start(wtpman,preamble & 0xf); } wtpman_addpacket(wtpman,buffer,len); wtplist_unlock(); } void process_lw_ctrl_packet(int index,struct sockaddr * addr, uint8_t * buffer, int len) { int sock = socklist[index].reply_sockfd; uint8_t * m = buffer+6; uint32_t val = ntohl(*((uint32_t*)(m))); printf ("VAL: %08X\n",val); /* first of all check preamble */ int version = LWTH_GET_VERSION(m); if (version != LW_VERSION){ cw_log_debug1("Discarding LWAPP packet, wrong verson"); return; } int l = LWTH_GET_LENGTH(m); printf ("LEN = %d\n",l); if (l+12 != len){ cw_log_debug1("Discarding LWAPP packet, wrong length"); return; } wtplist_lock(); struct wtpman * wtpman = wtplist_get(addr); if (!wtpman){ wtpman = wtpman_create(index,addr); if (!wtpman ){ cw_log(LOG_ERR,"Error creating wtpman: %s",strerror(errno)); wtplist_unlock(); return; } if (!wtplist_add(wtpman)){ cw_log(LOG_ERR,"Error adding wtpman: Too many wtp connections"); wtpman_destroy(wtpman); wtplist_unlock(); return; }; wtpman_lw_start(wtpman); } wtpman_lw_addpacket(wtpman,buffer,len); wtplist_unlock(); }
/** * 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; }
void onconnect_proc(NETWORK_HANDLE handle, void* userptr) { char addr[50]; sock_addr2str(network_get_peername(handle), addr); printf("%p connected. from %s\n", handle, addr); }