/* there is input available from the other side. read the input * (from link-level raw socket, or ip connection, or pipe depending on * how we were initialized.) * make sure the message is an ll_shell_ftp message (reject it and * return 0 otherwise). */ static int receive_message(message_t *msg) { struct sockaddr_ll recv_arg; socklen_t recv_arg_len; int result; if (cooked_in_file == NULL) { memset(&recv_arg, 0, sizeof(recv_arg)); recv_arg.sll_family = AF_PACKET; recv_arg.sll_ifindex = get_index.ifr_ifindex; recv_arg.sll_protocol = htons(ETH_P_ALL); recv_arg_len = sizeof(recv_arg); result = recvfrom(packet_socket, (void *) msg, sizeof(*msg), MSG_TRUNC, (struct sockaddr *) &recv_arg, &recv_arg_len); } else if (have_in_pio) { result = pio_read(&in_pio, (void *) msg, sizeof(*msg)); } else { result = read(in_fd, (void *) msg, sizeof(*msg)); } if (result == -1) { if (db[5].d) { fprintf(stderr, "recvfrom errno %d (%s)\n", errno, strerror(errno)); } result = -1; goto done; } if (((unsigned char *) msg)[0] == 0x41) { result = 0; goto done; } if (msg->eth_header.h_proto != htons(0x2985)) { result = 0; goto done; } if (0 != mac_cmp(my_mac_addr, msg->eth_header.h_dest)) { // fprintf(stderr, "rejecting msg not for me.\n"); result = 0; goto done; } if (!server || receiving) { if (0 != mac_cmp(dest_mac_addr, msg->eth_header.h_source)) { // fprintf(stderr, "rejecting msg not for me.\n"); result = 0; goto done; } } done: return result; }
wtp_handle_t* wtp_alloc(const char* device, wtp_aslan_msg_cb msg_cb) { if ((!device) || (!msg_cb)) { errno = EINVAL; return NULL; } int ret = -1; wtp_handle_t *handle = calloc(1, sizeof(wtp_handle_t)); if (!handle) { errno = ENOMEM; return NULL; } handle->wtp_state = WTP_STATE_NONE; handle->msg_cb = msg_cb; //for testing purposes only char hds_ip[] = "192.168.1.10"; handle->hds_port = ASLAN_PROTOCOL_PORT; handle->hello_interval_seconds = 5; /* UDP socket */ int s = -1; if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { free(handle); return NULL; } handle->udp_socket = s; if (pthread_mutex_init(&handle->hello_mutex, NULL) != 0) { free(handle); return NULL; } if (pthread_mutex_init(&handle->udp_mutex, NULL) != 0) { free(handle); return NULL; } if (pthread_mutex_init(&handle->ack_mutex, NULL) != 0) { free(handle); return NULL; } if (pthread_mutex_init(&handle->sta_mutex, NULL) != 0) { free(handle); return NULL; } if (pthread_mutex_init(&handle->monitor_mutex, NULL) != 0) { free(handle); return NULL; } handle->wtp_sta_hashmap = NULL; /* HDS parameters */ handle->hds_inet_addr.sin_family = AF_INET; if (!inet_aton(hds_ip, (struct in_addr*) &(handle->hds_inet_addr.sin_addr.s_addr))) { errno = EINVAL; close_wtp(handle); return NULL; } handle->hds_ip = ntohl(handle->hds_inet_addr.sin_addr.s_addr); /* interface name */ strncpy(handle->device, device, IFNAMSIZ - 1); /* interface IP */ struct ifreq ifr; ifr.ifr_addr.sa_family = AF_INET; strncpy(ifr.ifr_name, device, IFNAMSIZ - 1); if (ioctl(handle->udp_socket, SIOCGIFADDR, &ifr) == -1) { close_wtp(handle); return NULL; } handle->local_ip = ntohl(((struct sockaddr_in*)&ifr.ifr_addr)->sin_addr.s_addr); /* HDS sockaddr_in structure */ handle->hds_inet_addr.sin_addr.s_addr = htonl(handle->hds_ip); handle->hds_inet_addr.sin_family = AF_INET; handle->hds_inet_addr.sin_port = htons(handle->hds_port); /* UDP socket local port */ struct sockaddr_in address; memset((char*) &address, 0, sizeof(address)); address.sin_addr.s_addr = htonl(INADDR_ANY); address.sin_port = 0; address.sin_family = AF_INET; bind(handle->udp_socket, (struct sockaddr*) &address, sizeof(address)); struct sockaddr_in sin = {0}; socklen_t len = sizeof(sin); if (getsockname(handle->udp_socket, (struct sockaddr*)&sin, &len) == -1) { close_wtp(handle); return NULL; } handle->local_port = ntohs(sin.sin_port); wpa_printf(MSG_INFO, "INFO: UDP socket for ASLAN messages created, listening on port: %d\n", handle->local_port); /* create FIFO pipe producers and consumers */ pipe_t* recv_pipe = pipe_new(sizeof(aslan_msg_t *), 100); handle->msg_recv_producer = pipe_producer_new(recv_pipe); handle->msg_recv_consumer = pipe_consumer_new(recv_pipe); pipe_free(recv_pipe); pipe_t* send_pipe = pipe_new(sizeof(aslan_msg_t *), 100); handle->msg_send_producer = pipe_producer_new(send_pipe); handle->msg_send_consumer = pipe_consumer_new(send_pipe); pipe_free(send_pipe); /* start receiving thread for ASLAN messages */ if (pthread_create(&(handle->receive_thread), NULL, receive_msg_thread, (void*)handle) != 0) { errno = ENOMEM; close_wtp(handle); return NULL; } wpa_printf(MSG_INFO, "DEBUG: receiving thread for ASLAN messages created\n"); /* start processing thread for ASLAN messages */ if (pthread_create(&(handle->process_thread), NULL, process_msg_thread, (void*)handle) != 0) { errno = ENOMEM; close_wtp(handle); return NULL; } wpa_printf(MSG_INFO, "DEBUG: processing thread for ASLAN messages created\n"); /* start sending thread for ASLAN messages */ if (pthread_create(&(handle->send_thread), NULL, send_msg_thread, (void*)handle) != 0) { errno = ENOMEM; close_wtp(handle); return NULL; } wpa_printf(MSG_INFO, "DEBUG: sending thread for ASLAN messages created\n"); /* obtain HDS MAC address by a Hello message */ if (wtp_send_hello_msg(handle) == -1) { close_wtp(handle); return NULL; } /* Check ARP cache */ if (handle->local_ip != handle->hds_ip) { struct arpreq areq; memset(&areq, 0, sizeof(areq)); struct sockaddr_in* sockaddr = NULL; sockaddr = (struct sockaddr_in*) &(areq.arp_pa); sockaddr->sin_family = AF_INET; sockaddr->sin_addr.s_addr = htonl(handle->hds_ip); sockaddr = (struct sockaddr_in*) &(areq.arp_ha); sockaddr->sin_family = ARPHRD_ETHER; strncpy(areq.arp_dev, device, IFNAMSIZ - 1); int i = 0; unsigned char mac_loopback[] = {0, 0, 0, 0, 0, 0}; ioctl(s, SIOCGARP, (caddr_t) &areq); while ((i < 5) && (mac_cmp(areq.arp_ha.sa_data, mac_loopback))) { i++; sleep(1); ioctl(s, SIOCGARP, (caddr_t) &areq); } memcpy(handle->hds_mac, areq.arp_ha.sa_data, 6); if (mac_cmp(areq.arp_ha.sa_data, mac_loopback)) wpa_printf(MSG_WARNING, "WARNING: HDS MAC address obtaining failed\n"); else wpa_printf(MSG_INFO, "INFO: HDS MAC address found: "MACSTR"\n", MAC2STR(handle->hds_mac)); } else wpa_printf(MSG_INFO, "INFO: WTP started at loopback\n"); return handle; }
/* wait up to a tenth of a second to receive a sequence number back from the * other side. we are expecting the sequence number to equal msg_seq. * and, we are sent back a message length, which we expect to be equal to * msg_len. * return 0 iff everything is happy. */ static int recv_seq_message(int msg_len, int msg_seq) { int len, seq; message_t msg; int result; while (1) { if (have_in_pio) { result = pio_timed_read_ok(&in_pio, 1); if (result != 1) { if (db[5].d) { fprintf(stderr, "timeout waiting for response.\n"); } return 1; } } else { int result; struct timeval timer = {0, 100000}; fd_set read_set; int fd; FD_ZERO(&read_set); if (cooked_in_file == NULL) { fd = packet_socket; } else { fd = in_fd; } FD_SET(fd, &read_set); result = select(fd + 1, &read_set, 0, 0, &timer); if (result == -1) { perror("select problem"); return 1; } if (result != 1) { if (db[5].d) { fprintf(stderr, "timeout waiting for response.\n"); } return 1; } if (db[3].d) { fprintf(stderr, "recv_seq_message select returned %d: ", result); { int i; for (i = 0; i < fd + 1; i++) { if (FD_ISSET(i, &read_set)) { fprintf(stderr, "%d ", i); } } fprintf(stderr, "\n"); } } } result = receive_message(&msg); if (result == 0) { continue; } if (result == -1) { return -1; } if (0 != mac_cmp(my_mac_addr, msg.eth_header.h_dest)) { // fprintf(stderr, "rejecting msg not for me.\n"); continue; } if (msg.msg_type != recv_ok_msg && msg.msg_type != recv_err_msg && msg.msg_type != recv_err_stop_msg) { continue; } if (msg.msg_body_len != 8) { return -1; } len = ntohl(* (unsigned long int *) &msg.msg_body[0]); seq = ntohl(* (unsigned long int *) &msg.msg_body[4]); if (len != msg_len || seq != msg_seq) { return -1; } if (msg.msg_type == recv_err_msg) { return -1; } if (msg.msg_type == recv_err_stop_msg) { fprintf(stderr, "got recv_err_stop_msg from server!\n"); return(-1); } return 0; } }