/** * Find a good reply socket (only for IPv4) * @param sa source address * @return socket or -1 if no socket was found */ int socklist_find_reply_socket(struct sockaddr *sa, int port) { int bestindex = -1; int i; for (i = 0; i < socklist_len; i++) { /* we want only an unicast socket for reply */ if (socklist[i].type != SOCKLIST_UNICAST_SOCKET) continue; /* and we want only sockets with same sa_family */ if (sa->sa_family != socklist[i].addr.sa_family) continue; /* the first fd would be always the best, if we don't * find later a better one */ if (bestindex == -1) { bestindex = i; continue; } /* we want first the same port */ if (sock_getport(&socklist[i].addr) != port) { continue; } /* if we havn't already found a socket with same port * this is now our best socket*/ if (sock_getport(&socklist[bestindex].addr) != port) { bestindex = i; } /* the next checks only aply to IPv4 */ if (socklist[i].addr.sa_family != AF_INET) continue; /* get our source address and netmask */ uint32_t addr = ((struct sockaddr_in *) &socklist[i].addr)->sin_addr.s_addr; uint32_t mask = ((struct sockaddr_in *) &socklist[i].netmask)->sin_addr.s_addr; /* get source of requested address */ uint32_t saddr = ((struct sockaddr_in *) sa)->sin_addr.s_addr; /* if the request comes from the same subnet where our * socket is cconnected, this is our new best socked. * So we can serve AP's w*here no deault route is configured */ if ((addr & mask) == (saddr & mask)) { bestindex = i; } } if (bestindex != -1) return socklist[bestindex].sockfd; 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; }
struct wtpman *wtpman_create(int socklistindex, struct sockaddr *srcaddr) { struct wtpman *wtpman; wtpman = malloc(sizeof(struct wtpman)); if (!wtpman) return 0; memset(wtpman, 0, sizeof(struct wtpman)); int replyfd; 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)); free(wtpman); return NULL; } } else { replyfd = socklist[socklistindex].sockfd; } int sockfd = replyfd; //socklist[socklistindex].reply_sockfd; struct sockaddr dbgaddr; socklen_t dbgaddrl = sizeof(dbgaddr); getsockname(sockfd, &dbgaddr, &dbgaddrl); cw_dbg(DBG_INFO, "Creating wtpman on socket %d, %s:%d", sockfd, sock_addr2str(&dbgaddr), sock_getport(&dbgaddr)); //extern int conn_process_packet2(struct conn *conn, uint8_t * packet, int len, // struct sockaddr *from); wtpman->conn = conn_create(sockfd, srcaddr, 100); wtpman->conn->data_sock = socklist[socklistindex].data_sockfd; sock_copyaddr(&wtpman->conn->data_addr, (struct sockaddr *) &wtpman->conn->addr); // wtpman->conn->process_packet = conn_process_packet2; 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; return wtpman; }