📄 aodv_socket.c
字号:
/***************************************************************************** * * Copyright (C) 2001 Uppsala University and Ericsson AB. * Copyright (C) 2003 Simon Fraser University and NewMIC * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Authors: Erik Nordstr鰉, <erik.nordstrom@it.uu.se> * : Peter Lee <peter.lee@shaw.ca> * *****************************************************************************//* Uncomment if SOCK_RAW is to be used instead of SOCK_DGRAM. SOCK_RAW code is not finished though... *//* #define RAW_SOCKET */#include <sys/types.h>#ifdef NS_PORT#include "aodv-uu.h"#else#include <sys/socket.h>#include <netinet/in.h>#include <net/if.h>#ifdef RAW_SOCKET#include <netinet/udp.h>#endif /* RAW_SOCKET */#include "aodv_socket.h"#include "timer_queue.h"#include "aodv_rreq.h"#include "aodv_rerr.h"#include "aodv_rrep.h"#include "aodv_hello.h"#include "debug.h"#include "defs.h"#include "ipv6_utils.h"#include "address_areq.h"#include "address_arep.h"#endif /* NS_PORT */#ifndef NS_PORT#define SO_RECVBUF_SIZE 256*1024//PL:#ifndef _IPV6static char recv_buf[RECV_BUF_SIZE];#endif /* _IPV6 */static char send_buf[SEND_BUF_SIZE];extern int wait_on_reboot, hello_qual_threshold;static void aodv_socket_read(int fd);/* For some reason, this struct is not picked up from any header file * when compiling against ARM... Therefore it must be defined here. */#ifdef ARMstruct in_pktinfo { int ipi_ifindex; struct in_addr ipi_spec_dst; struct in_addr ipi_addr;};#endif /* ARM */#endif /* NS_PORT */void NS_CLASS aodv_socket_init(){#ifndef NS_PORT //PL:#ifdef _IPV6 struct sockaddr_in6 aodv_addr;#else struct sockaddr_in aodv_addr;#endif /* _IPV6 */ struct ifreq ifr; int i, retval = 0; int on = 1; int tos = IPTOS_LOWDELAY; int bufsize = SO_RECVBUF_SIZE; //PL: for IPv6 Multicast struct ipv6_mreq mreq6; int if_index; printf("aodv socket init...\n"); /* Create a UDP socket */ if (this_host.nif == 0) { fprintf(stderr, "aodv_socket_init: No interfaces configured\n"); exit(-1); } /* Open a socket for every AODV enabled interface */ for (i = 0; i < MAX_NR_INTERFACES; i++) { if (!DEV_NR(i).enabled) continue;#ifdef RAW_SOCKET DEV_NR(i).sock = socket(PF_INET, SOCK_RAW, IPPROTO_UDP);#else//PL:#ifdef _IPV6 DEV_NR(i).sock = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);#else DEV_NR(i).sock = socket(PF_INET, SOCK_DGRAM, 0);#endif /* _IPV6 */#endif /* RAW_SOCKET */ if (DEV_NR(i).sock < 0) { perror("aodv_socket_init: "); exit(-1); } /* Bind the socket to the AODV port number */ memset(&aodv_addr, 0, sizeof(aodv_addr)); //PL:#ifdef _IPV6 aodv_addr.sin6_family = AF_INET6; aodv_addr.sin6_port = htons(AODV_PORT); aodv_addr.sin6_addr = in6addr_any; //Doesn't need to do htonl, all 0#else aodv_addr.sin_family = AF_INET; aodv_addr.sin_port = htons(AODV_PORT); aodv_addr.sin_addr.s_addr = htonl(INADDR_ANY);#endif /* _IPV6 */ //PL: Change the sizeof(struct sockaddr) to sizeof(aodv_addr) /* retval = bind(DEV_NR(i).sock, (struct sockaddr *) &aodv_addr, sizeof(struct sockaddr)); */ retval = bind(DEV_NR(i).sock, (struct sockaddr *) &aodv_addr, sizeof(aodv_addr)); if (retval < 0) { perror("aodv_socket_init: Bind failed "); exit(-1); } //PL: IPv6 doesn't have broadcast#ifdef _IPV6 memcpy(&mreq6.ipv6mr_multiaddr, &(DEV_NR(i).multicast), sizeof(struct in6_addr)); //copy_in6_addr(&mreq6.ipv6mr_multiaddr, &(DEV_NR(i).multicast)); mreq6.ipv6mr_interface = DEV_NR(i).ifindex; if_index = DEV_NR(i).ifindex; //PL: debug - For testing purpose /* printf("DEV_NR(%d).ifindex = %d\nMulticast Address = ", i, if_index); print_ipv6_addr(DEV_NR(i).multicast); printf("DEV_NR(%d).name = %s\n", i, DEV_NR(i).ifname); */ if(setsockopt(DEV_NR(i).sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq6, sizeof(mreq6))<0) { fprintf(stderr, "aodv_socket_init: IPV6_ADD_MEMBERSHIP failed for %s", DEV_NR(i).ifname); perror(" "); exit(-1); } if(setsockopt(DEV_NR(i).sock, IPPROTO_IPV6, IPV6_MULTICAST_IF, &if_index, sizeof(if_index))<0) { fprintf(stderr, "aodv_socket_init: IPV6_MULTICAST_IF failed for %s", DEV_NR(i).ifname); perror(" "); exit(-1); }#else if (setsockopt(DEV_NR(i).sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof(int)) < 0) { perror("aodv_socket_init: SO_BROADCAST failed "); exit(-1); }#endif /* _IPV6 */ memset(&ifr, 0, sizeof(struct ifreq)); strcpy(ifr.ifr_name, DEV_NR(i).ifname); //PL: This might still the same for IPv6 if (setsockopt(DEV_NR(i).sock, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) < 0) { fprintf(stderr, "aodv_socket_init: SO_BINDTODEVICE failed for %s", DEV_NR(i).ifname); perror(" "); exit(-1); } if (setsockopt(DEV_NR(i).sock, SOL_SOCKET, SO_PRIORITY, &tos, sizeof(int)) < 0) { perror("aodv_socket_init: Setsockopt SO_PRIORITY failed "); exit(-1); }#ifdef RAW_SOCKET /* We provide our own IP header... */ if (setsockopt(DEV_NR(i).sock, SOL_IP, IP_HDRINCL, &on, sizeof(int)) < 0) { perror("aodv_socket_init: Setsockopt IP_HDRINCL failed "); exit(-1); }#else #ifdef _IPV6 if (setsockopt(DEV_NR(i).sock, IPPROTO_IPV6, IPV6_PKTINFO, &on, sizeof(int)) < 0) { perror("aodv_socket_init: Setsockopt IPV6_PKTINFO failed "); exit(-1); } //PL: IPv6 has HOP_LIMIT instead of TTL if (setsockopt(DEV_NR(i).sock, IPPROTO_IPV6, IPV6_HOPLIMIT, &on, sizeof(int)) < 0) { perror("aodv_socket_init: Setsockopt IPV6_HOPLIMIT failed "); exit(-1); }#else if (setsockopt(DEV_NR(i).sock, SOL_IP, IP_PKTINFO, &on, sizeof(int)) < 0) { perror("aodv_socket_init: Setsockopt IP_PKTINFO failed "); exit(-1); } if (setsockopt(DEV_NR(i).sock, SOL_IP, IP_RECVTTL, &on, sizeof(int)) < 0) { perror("aodv_socket_init: Setsockopt IP_TTL failed "); exit(-1); }#endif /* _IPV6 */#endif /* RAW_SOCKET */ /* Set max allowable receive buffer size... */ for (;; bufsize -= 1024) { if (setsockopt(DEV_NR(i).sock, SOL_SOCKET, SO_RCVBUF, (char *) &bufsize, sizeof(bufsize)) == 0) { log(LOG_NOTICE, 0, "aodv_socket_init: Receive buffer size set to %d", bufsize); break; } if (bufsize < RECV_BUF_SIZE) { log(LOG_ERR, 0, "aodv_socket_init: Could not set receive buffer size"); exit(-1); } } retval = attach_callback_func(DEV_NR(i).sock, aodv_socket_read); if (retval < 0) { perror("aodv_socket_init: register input handler failed "); exit(-1); } }#endif /* NS_PORT */}//PL:#ifdef _IPV6/* PL: Note that ttl change to hop_limit */void NS_CLASS aodv_socket_process_packet(AODV_msg * aodv_msg, int len, struct in6_addr src, struct in6_addr dst, int hop_limit, unsigned int ifindex)#elsevoid NS_CLASS aodv_socket_process_packet(AODV_msg * aodv_msg, int len, u_int32_t src, u_int32_t dst, int ttl, unsigned int ifindex)#endif /* _IPV6 */{ /* Check if this was a HELLO message... */ //PL:#ifdef _IPV6 if ((aodv_msg->type == AODV_RREP && hop_limit == 1 && !(memcmp(&dst, &ipv6_multicast_addr, sizeof(struct in6_addr))))){ hello_process((RREP *) aodv_msg, len, ifindex); return; }#else if ((aodv_msg->type == AODV_RREP && ttl == 1 && dst == AODV_BROADCAST)) { hello_process((RREP *) aodv_msg, len, ifindex); return; }#endif /* _IPV6 */ /* Treat this non-hello message as a HELLO so that neighbors are * added to the routing table */ hello_process_non_hello(aodv_msg, src, ifindex); /* Check what type of msg we received and call the corresponding function to handle the msg... */ switch (aodv_msg->type) { case AODV_RREQ: printf("ZJH:aodv_socket_process_packet:aodv rreq\n");#ifdef _IPV6 rreq_process((RREQ *) aodv_msg, len, src, dst, hop_limit, ifindex);#else rreq_process((RREQ *) aodv_msg, len, src, dst, ttl, ifindex);#endif /*_IPV6 */ break; case AODV_RREP: printf("ZJH:aodv_socket_process_packet:aodv rrep\n");#ifdef _IPV6 rrep_process((RREP *) aodv_msg, len, src, dst, hop_limit, ifindex);#else rrep_process((RREP *) aodv_msg, len, src, dst, ttl, ifindex);#endif /*_IPV6 */ break; case AODV_RERR: printf("ZJH:aodv_socket_process_packet:aodv rerr\n"); rerr_process((RERR *) aodv_msg, len, src, dst); break; case AODV_RREP_ACK: printf("ZJH:aodv_socket_process_packet:aodv rrep_ack\n"); rrep_ack_process((RREP_ack *) aodv_msg, len, src, dst); break; case AODV_AREQ: printf("aodv_socket_process_packet:aodv areq\n"); areq_process((AREQ *)aodv_msg,len,src,dst,hop_limit,ifindex); break; case AODV_AREP: printf("aodv_socket_process_packet:aodv arep\n"); arep_process((AREP *)aodv_msg,len,src,dst,hop_limit,ifindex); break; default:#ifdef _IPV6 log(LOG_WARNING, 0, "aodv_socket_read: Unknown msg type %u rcvd from %s to %s", aodv_msg->type, ip6_to_str(src), ip6_to_str(dst));#else log(LOG_WARNING, 0, "aodv_socket_read: Unknown msg type %u rcvd from %s to %s", aodv_msg->type, ip_to_str(src), ip_to_str(dst));#endif /* _IPV6 */ }}#ifdef NS_PORTvoid NS_CLASS recvAODVUUPacket(Packet * p){ int len, i, ttl = 0; u_int32_t src, dst; struct hdr_cmn *ch = HDR_CMN(p); struct hdr_ip *ih = HDR_IP(p); hdr_aodvuu *ah = HDR_AODVUU(p); src = ih->saddr(); dst = ih->daddr(); len = ch->size() - IP_HDR_LEN; ttl = ih->ttl(); AODV_msg *aodv_msg = (AODV_msg *) recv_buf; /* Only handle AODVUU packets */ assert(ch->ptype() == PT_AODVUU); /* Only process incoming packets */ assert(ch->direction() == hdr_cmn::UP); /* Copy message to receive buffer */ memcpy(recv_buf, ah, RECV_BUF_SIZE); /* Drop or deallocate packet, depending on the TTL */ /* if (ttl == 1) *//* drop(p, DROP_RTR_TTL); *//* else */ Packet::free(p); /* Ignore messages generated locally */ for (i = 0; i < MAX_NR_INTERFACES; i++) if (this_host.devs[i].enabled && memcmp(&src, &this_host.devs[i].ipaddr, sizeof(u_int32_t)) == 0) return; aodv_socket_process_packet(aodv_msg, len, src, dst, ttl, NS_IFINDEX);}#elsestatic void aodv_socket_read(int fd){ //PL:#ifdef _IPV6 struct in6_addr src, dst; int i, len, hop_limit = 0, moveon = 0; //PL: debug /*//ZJH*/u_int8_t *debug_msg;#else u_int32_t src, dst; int i, len, ttl = 0;#endif /* _IPV6 */ AODV_msg *aodv_msg;#ifdef RAW_SOCKET int iph_len; struct iphdr *iph; struct udphdr *udph; len = recvfrom(fd, recv_buf, RECV_BUF_SIZE, 0, NULL, NULL); if (len < 0 || len < IPHDR_SIZE) { log(LOG_WARNING, 0, "aodv_socket_read: receive ERROR!"); return; } /* Parse the IP header */ iph = (struct iphdr *) recv_buf; src = ntohl(iph->saddr); dst = ntohl(iph->daddr); ttl = iph->ttl; iph_len = iph->ihl << 2; udph = (struct udphdr *) (recv_buf + iph_len); if (ntohs(udph->dest) != AODV_PORT && ntohs(udph->source) != AODV_PORT) return; /* Ignore messages generated locally */ for (i = 0; i < MAX_NR_INTERFACES; i++) if (this_host.devs[i].enabled && memcmp(&src, &this_host.devs[i].ipaddr, sizeof(u_int32_t)) == 0) return; aodv_msg = (AODV_msg *) (recv_buf + iph_len + sizeof(struct udphdr)); len = ntohs(udph->len) - sizeof(struct udphdr);#else //PL:#ifdef _IPV6 struct sockaddr_in6 src_addr; //PL: Change to use recvmsg unsigned char buffer[IP_MAXPACKET]; unsigned char msgbuffer[1024]; struct iovec iov = { (void *)&buffer, IP_MAXPACKET }; struct sockaddr_in6 addr; struct msghdr msg = { (void *)&addr, sizeof(addr), &iov, 1, (void *)&msgbuffer, sizeof(msgbuffer), 0 }; struct cmsghdr *cmsg; struct in6_pktinfo pktinfo;#else struct sockaddr_in src_addr; struct msghdr msg; union { struct cmsghdr cm; char control[CMSG_SPACE(sizeof(int)) + CMSG_SPACE(sizeof(struct in_pktinfo))]; } control_union; struct cmsghdr *cmsg; struct in_pktinfo pktinfo; int sockaddr_len = sizeof(struct sockaddr_in); msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_iov = NULL; msg.msg_iovlen = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -