📄 aodv_socket.c
字号:
msg.msg_control = control_union.control; msg.msg_controllen = sizeof(control_union.control);#endif /* _IPV6 */ //PL: debug //printf("aodv_socket_read is called\n"); /* Get the information control message first */ if ((len = recvmsg(fd, &msg, 0)) < 0) { log(LOG_WARNING, 0, "aodv_socket_read: recvmsg ERROR!"); return; } //PL: debug //printf("control message length = %d\n", len); //PL: aodv message is in msg.msg_iov->iov_base /* Read the data payload (i.e. AODV msg) */ /* len = recvfrom(fd, recv_buf, RECV_BUF_SIZE, 0, (struct sockaddr *) &src_addr, &sockaddr_len); if (len < 0) { log(LOG_WARNING, 0, "aodv_socket_read: receive ERROR!"); return; } aodv_msg = (AODV_msg *) (recv_buf); */ memcpy(&src_addr, msg.msg_name, sizeof(struct sockaddr_in6)); aodv_msg = (AODV_msg *) msg.msg_iov->iov_base; //PL: use IPv6 ntoh#ifdef _IPV6 copy_in6_addr(&src, &src_addr.sin6_addr); printf("ZJH:aodv_socket_read called,source addr:%s\n",ip6_to_str(src));#else src = ntohl(src_addr.sin_addr.s_addr);#endif /* _IPV6 */ /* Ignore messages generated locally */ for (i = 0; i < MAX_NR_INTERFACES; i++) //PL:#ifdef _IPV6 if (this_host.devs[i].enabled && memcmp(&src, &this_host.devs[i].ipaddr, sizeof(struct in6_addr)) == 0)#else if (this_host.devs[i].enabled && memcmp(&src, &this_host.devs[i].ipaddr, sizeof(u_int32_t)) == 0)#endif /* _IPV6 */ { //PL: debug //printf("This is local generated message\n"); printf("ZJH:This is local generated message!!!\n"); return; } //PL: debug - print aodv_message /*ZJH*/ printf("ZJH:This is received message!!!\n"); debug_msg = (char *) (msg.msg_iov->iov_base); printf("aodv_msg length = %d\naodv_msg =\n%2.2x ", len, debug_msg[0]); for(i = 1 ; i < len; i ++) { printf("%2.2x ", debug_msg[i]); if(!((i+1)%10)) printf("\n"); } printf("\n"); /*ZJH*/ //PL:#ifdef _IPV6 //PL: Need to verify CMSG_NXTHDR work as it mention in the original // doesn't work across different RedHat Linux for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { //PL: debug //printf("cmsg->cmsg_type = %d\n", cmsg->cmsg_type); if (cmsg->cmsg_type == IPV6_HOPLIMIT) { hop_limit = (int) *CMSG_DATA(cmsg); //PL: Not sure why they do it this way //hopptr = (int *) CMSG_DATA(cmsg); //hops = *hopptr; //PL: debug //printf("cmsg_type = IPV6_HOPLIMIT, hop_limit = %d\n", hop_limit); printf("ZJH:cmsg_type = IPV6_HOPLIMIT, hop_limit = %d\n", hop_limit); } if (cmsg->cmsg_type == IPV6_PKTINFO) { memcpy(&pktinfo, CMSG_DATA(cmsg), sizeof(pktinfo)); //PL: Don't need to copy out //&pktinfo = (struct in6_pktinfo *) CMSG_DATA(cmsg); //memcpy(&daddr, &pktinfo.ipi6_addr, sizeof(struct in6_addr)); //ifindex = pktinfo.ipi6_ifindex; //PL: debug /* printf("cmsg_type = IPV6_PKTINFO, pktinfo.ipi6_ifindex = %d\n", pktinfo.ipi6_ifindex); */ printf("ZJH:cmsg_type = IPV6_PKTINFO, pktinfo.ipi6_ifindex = %d\n", pktinfo.ipi6_ifindex); moveon = 1; } } copy_in6_addr(&dst, &pktinfo.ipi6_addr); //PL: debug //printf("aodv_socket_read: dst = %s\n", ip6_to_str(dst)); printf("ZJH:dst = %s!!!\n", ip6_to_str(dst));#else /* Get the TTL and pktinfo struct (destination address) from the control messages... For some reason the correct use of the CMSG(3) macros using CMSG_NXTHDR does not work across different Red Hat versions (6.2 vs 7.2), but this code seem to work: */ cmsg = CMSG_FIRSTHDR(&msg); for (i = 0; i < 2; i++) { if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_TTL) { memcpy(&ttl, CMSG_DATA(cmsg), sizeof(int)); cmsg = (void *) cmsg + CMSG_SPACE(sizeof(int)); } else if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_PKTINFO) { memcpy(&pktinfo, CMSG_DATA(cmsg), sizeof(struct in_pktinfo)); cmsg = (void *) cmsg + CMSG_SPACE(sizeof(struct in_pktinfo)); } } dst = ntohl(pktinfo.ipi_addr.s_addr);#endif /* _IPV6 */#endif /* RAW_SOCKET *///PL:#ifdef _IPV6 if(moveon) { //PL: debug /* printf("aodv_socket_read: pktinfo.ipi6_ifindex = %d\n", pktinfo.ipi6_ifindex); */ aodv_socket_process_packet(aodv_msg, len, src, dst, hop_limit, pktinfo.ipi6_ifindex); } else { printf("cannot retrieve cmsg correct,"); printf("will not proceed with aodv_socket_process_packet.\n"); }#else aodv_socket_process_packet(aodv_msg, len, src, dst, ttl, pktinfo.ipi_ifindex);#endif /* _IPV6 */}#endif /* NS_PORT *///PL:#ifdef _IPV6void aodv_socket_send(AODV_msg * aodv_msg, struct in6_addr dst, int len, u_int8_t hop_limit, struct dev_info *dev)#elsevoid NS_CLASS aodv_socket_send(AODV_msg * aodv_msg, u_int32_t dst, int len, u_int8_t ttl, struct dev_info *dev)#endif /* _IPV6 */{ int retval = 0;#ifndef NS_PORT //PL:#ifdef _IPV6 struct sockaddr_in6 dst_addr; int hop_limit_send; struct iovec iov[1]; struct msghdr msg; struct cmsghdr *cmsg; int cmsglen; struct in6_pktinfo pinfo;#else struct sockaddr_in dst_addr;#endif /* _IPV6 */#ifdef RAW_SOCKET struct iphdr *iph; struct udphdr *udph; if (wait_on_reboot && aodv_msg->type == AODV_RREP) return; /* Create a IP header around the packet... The AODV msg is already located in the send buffer and referenced by the in parameter "aodv_msg". */ iph = (struct iphdr *) send_buf; iph->tot_len = htons(IPHDR_SIZE + sizeof(struct udphdr) + len); iph->saddr = htonl(dev->ipaddr); iph->daddr = htonl(dst); iph->ttl = ttl; udph = (struct udphdr *) (send_buf + IPHDR_SIZE); udph->len = htons(len + sizeof(struct udphdr));#else /* Not RAW_SOCKET */ //PL: debug //printf("aodv_socket_send is called\n"); /* If we are in waiting phase after reboot, don't send any RREPs */ if (wait_on_reboot && aodv_msg->type == AODV_RREP) return; //PL:#ifdef _IPV6 //PL: I guess is IPV6_UNICAST_HOPS, instead of IPV6_MULTICAST_HOPS //PL: I think we might need to check if the address is for multicast over here //PL: For some reason, setsockopt doesn't like to take u_int8_t hop_limit_send = hop_limit; if (setsockopt(dev->sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *) &hop_limit_send, sizeof(hop_limit_send)) == -1) { perror("setsockopt IPV6_MULTICAST_HOPS"); return; } //PL: Just set the hop limit, doesn't care it is unicast or not if (setsockopt(dev->sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, (char *) &hop_limit_send, sizeof(hop_limit_send)) == -1) { perror("setsockopt IPV6_UNICAST_HOPS"); return; }#else /* Set the ttl we want to send with */ if (setsockopt(dev->sock, SOL_IP, IP_TTL, &ttl, sizeof(ttl)) < 0) { log(LOG_WARNING, 0, "aodv_socket_send: Failed to set TTL!!!"); return; }#endif /* _IPV6 */#endif /* RAW_SOCKET */ memset(&dst_addr, 0, sizeof(dst_addr)); //PL:#ifdef _IPV6 dst_addr.sin6_family = AF_INET6; copy_in6_addr(&dst_addr.sin6_addr, &dst); dst_addr.sin6_port = htons(AODV_PORT);#else dst_addr.sin_family = AF_INET; dst_addr.sin_addr.s_addr = htonl(dst); dst_addr.sin_port = htons(AODV_PORT);#endif /* _IPV6 */#else /* if define NS_PORT */ /* NS_PORT: Sending of AODV_msg messages to other AODV-UU routing agents by encapsulating them in a Packet. Note: This method is _only_ for sending AODV packets to other routing agents, _not_ for forwarding "regular" IP packets! */ /* If we are in waiting phase after reboot, don't send any RREPs */ if (wait_on_reboot && aodv_msg->type == AODV_RREP) return; /* NS_PORT: Don't allocate packet until now. Otherwise packet uid (unique ID) space is unnecessarily exhausted at the beginning of the simulation, resulting in uid:s starting at values greater than 0. */ Packet *p = allocpkt(); struct hdr_cmn *ch = HDR_CMN(p); struct hdr_ip *ih = HDR_IP(p); hdr_aodvuu *ah = HDR_AODVUU(p); // Clear AODVUU part of packet memset(ah, '\0', ah->size()); // Copy message contents into packet memcpy(ah, aodv_msg, len); // Set common header fields ch->ptype() = PT_AODVUU; ch->direction() = hdr_cmn::DOWN; ch->size() = IP_HDR_LEN + len; ch->iface() = -2; ch->error() = 0; ch->prev_hop_ = (nsaddr_t) dev->ipaddr; // Set IP header fields ih->saddr() = (nsaddr_t) dev->ipaddr; ih->daddr() = (nsaddr_t) dst; ih->ttl() = ttl; // Note: Port number for routing agents, not AODV port number! ih->sport() = RT_PORT; ih->dport() = RT_PORT; // Fake success retval = len;#endif /* NS_PORT */ //PL: use sendmsg instead of sendto memset(&pinfo, 0, sizeof(pinfo)); memcpy(&pinfo.ipi6_addr, &dev->ipaddr, sizeof(struct in6_addr)); //PL: I dpn't think we need to specify the ipi6_ifindex /* pinfo.ipi6_ifindex = dev->ifindex; */ cmsglen = CMSG_SPACE(sizeof(pinfo)); cmsg = malloc(cmsglen); if (cmsg == NULL) { perror(__FUNCTION__); return; } cmsg->cmsg_len = CMSG_LEN(sizeof(pinfo)); cmsg->cmsg_level = IPPROTO_IPV6; cmsg->cmsg_type = IPV6_PKTINFO; memcpy(CMSG_DATA(cmsg), &pinfo, sizeof(pinfo)); iov[0].iov_base = (unsigned char *)aodv_msg; iov[0].iov_len = len; msg.msg_control = cmsg; msg.msg_controllen = cmsglen; msg.msg_iov = iov; msg.msg_iovlen = 1; msg.msg_name = (void *)&dst_addr; msg.msg_namelen = sizeof(dst_addr); /* If we broadcast this message we update the time of last broadcast to prevent unnecessary broadcasts of HELLO msg's */ //PL: //PL:debug //printf("aodv_socket_send is called.\n");#ifdef _IPV6 if (!(memcmp(&dst, &ipv6_multicast_addr, sizeof(ipv6_multicast_addr)))) {#else if (dst == AODV_BROADCAST) {#endif /* _IPV6 */ gettimeofday(&this_host.bcast_time, NULL);#ifdef NS_PORT ch->addr_type() = NS_AF_NONE; sendPacket(p, 0, 0.0);#else //PL:debug /*ZJH*/ //printf("send_buf size = %d send_buf:%s\n", strlen(send_buf),send_buf); printf("dst_addr.sin6_addr = %s len = %d ttl=%d\n", ip6_to_str(dst_addr.sin6_addr), len,hop_limit); printf("aodv_socket_send is calling sendmsg.\n"); /*ZJH*/ /* retval = sendto(dev->sock, send_buf, len, 0, (struct sockaddr *) &dst_addr, sizeof(dst_addr)); */ retval = sendmsg(dev->sock, &msg, 0); if (retval < 0) { //PL:#ifdef _IPV6 log(LOG_WARNING, errno, "aodv_socket_send: Failed send to %s", ip6_to_str(dst));#else log(LOG_WARNING, errno, "aodv_socket_send: Failed send to %s", ip_to_str(dst));#endif /* _IPV6 */ return; }#endif } else {#ifdef NS_PORT ch->addr_type() = NS_AF_INET; /* We trust the decision of next hop for all AODV messages... */ /* Add jitter, even for unicast control messages. */ sendPacket(p, dst, 0.03 * Random::uniform());#else //PL:debug /* printf("aodv_socket_send: sendmsg to not multicast address\n"); retval = sendto(dev->sock, send_buf, len, 0, (struct sockaddr *) &dst_addr, sizeof(dst_addr)); */ retval = sendmsg(dev->sock, &msg, 0); if (retval < 0) { //PL:#ifdef _IPV6 log(LOG_WARNING, errno, "aodv_socket_send: Failed send to %s", ip6_to_str(dst));#else log(LOG_WARNING, errno, "aodv_socket_send: Failed send to %s", ip_to_str(dst));#endif /* _IPV6 */ return; }#endif } /* Do not print hello msgs... */ //PL:#ifdef _IPV6 if (!(aodv_msg->type == AODV_RREP && !(memcmp(&dst, &ipv6_multicast_addr, sizeof(ipv6_multicast_addr))))){ DEBUG(LOG_INFO, 0, "aodv_socket_send: AODV msg to %s hop limit=%d (%d bytes)", ip6_to_str(dst), hop_limit, retval); printf("aodv_socket_send: AODV msg to %s hop limit=%d (%d bytes)\n", ip6_to_str(dst), hop_limit, retval); }#else if (!(aodv_msg->type == AODV_RREP && (dst == AODV_BROADCAST))) DEBUG(LOG_INFO, 0, "aodv_socket_send: AODV msg to %s ttl=%d (%d bytes)", ip_to_str(dst), ttl, retval);#endif /* _IPV6 */}AODV_msg *NS_CLASS aodv_socket_new_msg(void){#if defined(RAW_SOCKET) && !defined(NS_PORT) struct iphdr *iph; struct udphdr *udph; /* Initialize IP header, kernel fills in zero:ed values... */ memset(send_buf, '\0', SEND_BUF_SIZE); iph = (struct iphdr *) send_buf; iph->version = IPVERSION; iph->ihl = (IPHDR_SIZE >> 2); iph->tos = 0; iph->id = 0; iph->frag_off = 0; iph->protocol = IPPROTO_UDP; iph->check = 0; udph = (struct udphdr *) (send_buf + IPHDR_SIZE); udph->source = htons(AODV_PORT); udph->dest = htons(AODV_PORT); udph->check = 0; return (AODV_msg *) (send_buf + IPHDR_SIZE + sizeof(struct udphdr));#else memset(send_buf, '\0', SEND_BUF_SIZE); return (AODV_msg *) (send_buf);#endif /* RAW_SOCKET */}/* Copy an existing AODV message to the send buffer */AODV_msg *NS_CLASS aodv_socket_queue_msg(AODV_msg * aodv_msg, int size){#if defined(RAW_SOCKET) && !defined(NS_PORT) memcpy((char *) (send_buf + IPHDR_SIZE), aodv_msg, size); return (AODV_msg *) (send_buf + IPHDR_SIZE);#else memcpy((char *) (send_buf), aodv_msg, size); return (AODV_msg *) (send_buf);#endif /* RAW_SOCKET */}void aodv_socket_cleanup(void){#ifndef NS_PORT int i; for (i = 0; i < MAX_NR_INTERFACES; i++) { if (!DEV_NR(i).enabled) continue; close(DEV_NR(i).sock); }#endif /* NS_PORT */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -