📄 aodvsocket.c
字号:
/* * Copyright (C) 2001, University of California, Santa Barbara * * 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. * * Other copyrights might apply to parts of this software and are so * noted when applicable. *//* * Parts of this program has been derived from PIM sparse-mode pimd. * The pimd program is covered by the license in the accompanying file * named "LICENSE.pimd". * * The pimd program is COPYRIGHT 1998 by University of Southern California. * */#include <arpa/inet.h>#include <errno.h>#include <netinet/ip.h>#include <signal.h>#include <string.h>#include <sys/types.h>#include <sys/socket.h>#include "aodvMsg.h"#include "aodvPktInfo.h"#include "callout.h"#include "const.h"#include "debug.h"#include "inet.h"#include "routingTable.h"#include "rreq.h"#include "rrep.h"#include "main.h"u_int32_t mySeqNum = 1;u_int32_t broadcastId = 1;char *aodv_recv_buf; /* input packet buffer */char *aodv_send_buf; /* output packet buffer */int aodv_socket = -1;static void read_aodvSocket __P((int f, fd_set *rfd));static void accept_aodvSocket __P((struct AodvPktInfo *info, int recvlen));void k_set_rcvbuf(int socket, int bufsize, int minsize);void k_hdr_include(int socket, int bool);/* * create the aodvSocket */void new_aodvSocket() { struct sockaddr_in my_addr; const int yes = 1; const int zero = 0; int test=0; int sizeoftest; //had to use DGRAM, 0 so that multicast could be used //YOU CAN'T USE MULTICAST WITH RAW, or any other protocol if ((aodv_socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { log(LOG_ERR, FALSE, "failed to create AODV socket"); } else { trace(TRACE_INIT|TRACE_AODV_SOCKET, "created AODV socket=%i",aodv_socket); } if (setsockopt(aodv_socket, SOL_SOCKET, SO_BROADCAST, &yes, sizeof(yes)) < 0){ log(LOG_ERR, FALSE, "setsockopt SO_BROADCAST failed:%i",errno); } if (getsockopt(aodv_socket, SOL_SOCKET, SO_PRIORITY , &test, &sizeoftest) < 0){ log(LOG_ERR, FALSE, "getsockopt SO_PRIORITY failed:%i",errno); }else{ trace(TRACE_CUR,"getsockopt SO_PRIORITY = %i",test); } if (setsockopt(aodv_socket, SOL_SOCKET, SO_PRIORITY , &zero, sizeof(zero)) < 0){ log(LOG_ERR, FALSE, "setsockopt SO_PRIORITY failed:%i",errno); } if (setsockopt(aodv_socket, SOL_SOCKET, SO_PRIORITY , &zero, sizeof(zero)) < 0){ log(LOG_ERR, FALSE, "setsockopt SO_PRIORITY failed:%i",errno); } /* Tell socket to send IP_TTL for received messages. */ if (setsockopt(aodv_socket, SOL_IP, IP_RECVTTL, &yes, sizeof(yes)) < 0){ log(LOG_ERR, FALSE, "setsockopt IP_RECVTTL failed:%i",errno); } /* Tell socket to send PKTINFO for received messages. */ if (setsockopt(aodv_socket, SOL_IP, IP_PKTINFO, &yes, sizeof(yes)) < 0){ log(LOG_ERR, FALSE, "setsockopt IP_PKTINFO failed:%i",errno); } aodv_recv_buf = malloc(RECV_BUF_SIZE); aodv_send_buf = malloc(RECV_BUF_SIZE); my_addr.sin_family = AF_INET; /* host byte order */ my_addr.sin_port = htons(AODV_PORT); /* short, network byte order */ my_addr.sin_addr.s_addr = INADDR_ANY; bzero(&(my_addr.sin_zero), 8); /* zero the rest of the struct */ if (bind(aodv_socket , (struct sockaddr *)&my_addr , sizeof(struct sockaddr)) < 0){ log(LOG_ERR, FALSE, "Can't bind AODV socket"); } else { trace(TRACE_INIT|TRACE_AODV_SOCKET, "bind successful for AODV socket"); } if (register_input_handler(aodv_socket, read_aodvSocket) == ERROR){ log(LOG_ERR, FALSE, \ "cannot register aodv_read() as an input handler"); }}struct a_in_pktinfo{ unsigned int ipi_ifindex; /* Interface index */ struct in_addr ipi_spec_dst; /* Routing destination address */ struct in_addr ipi_addr; /* Header Destination address */};union control_union { struct cmsghdr cm; char control[CMSG_SPACE(sizeof(int)) + CMSG_SPACE(sizeof(struct a_in_pktinfo))];};//used to print out ip addresseschar s1[19], s2[19]; /* Read an AODV message */static void read_aodvSocket(int f, fd_set *rfd) { register int aodv_recvlen; register int omask; int addr_len = sizeof(struct sockaddr_in); struct sockaddr_in their_addr; struct cmsghdr *cmsg; struct msghdr msgh; int cmsgi; struct a_in_pktinfo pktinfo; int *ttlptr; int received_ttl = 0; struct AodvPktInfo info; union control_union control_un; trace(TRACE_AODV_SOCKET, FALSE,"read_aodvSocket"); msgh.msg_name = NULL; msgh.msg_namelen = 0; msgh.msg_iov = NULL; msgh.msg_iovlen = 0; msgh.msg_control = control_un.control; msgh.msg_controllen = sizeof(control_un.control); if (recvmsg (aodv_socket, &msgh, MSG_PEEK) == -1){ log(LOG_ERR, TRUE,"read_aodvSocket recmsg ERROR=%i",errno); } aodv_recvlen = recvfrom(aodv_socket, aodv_recv_buf, RECV_BUF_SIZE, 0, (struct sockaddr *)&their_addr, &addr_len); trace(TRACE_AODV_SOCKET,"aodv_read:their_addr.sin_addr.s_addr=%s" ,inet_fmt_n(their_addr.sin_addr.s_addr,s1)); if (aodv_recvlen < 0) { trace(TRACE_AODV_SOCKET, "aodv_read:no length read from socket"); return; } else { trace(TRACE_AODV_SOCKET, "aodv_read:read %i bytes",aodv_recvlen); omask = sigblock(sigmask(SIGALRM)); /* Get the TLL, set <received_ttl>. */ cmsg = CMSG_FIRSTHDR(&msgh); if (msgh.msg_controllen == 40) { for (cmsgi = 0; cmsgi < 2; cmsgi++) { if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_TTL) { ttlptr = (int *) CMSG_DATA(cmsg); received_ttl = *ttlptr; 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 a_in_pktinfo)); cmsg = (void*)cmsg + CMSG_SPACE(sizeof(struct a_in_pktinfo)); } } }else{ log(LOG_ERR,TRUE,"read_aodvSocket:HEADER NOT INCLUDED"); } /* drop packets sent from this node. prevents bouncing messages. */ if((pktinfo.ipi_addr.s_addr == BROADCAST) && (their_addr.sin_addr.s_addr == getip())){ trace(TRACE_AODV_SOCKET ,"aodv_read:broadcast packet from self ignored"); return; } if((pktinfo.ipi_addr.s_addr == BROADCAST) && (their_addr.sin_addr.s_addr == 0)){ trace(TRACE_AODV_SOCKET ,"aodv_read:broadcast packet from 0.0.0.0 packet ignored"); return; } info.src = their_addr.sin_addr.s_addr; //if this is a broadcast packet re-address it to me if(pktinfo.ipi_addr.s_addr == BROADCAST){ trace(TRACE_AODV_SOCKET,"read_aodvSocket:info->dest was BROADCAST"); info.dest = getip(); } else { info.dest = pktinfo.ipi_addr.s_addr; } info.ttl = received_ttl; trace(TRACE_AODV_SOCKET,"read_aodvSocket:info->src=%s" ,inet_fmt_n(info.src,s1)); trace(TRACE_AODV_SOCKET,"read_aodvSocket:info->dest=%s" ,inet_fmt_n(info.dest,s1)); trace(TRACE_AODV_SOCKET,"read_aodvSocket:info->ttl=%u" ,info.ttl); accept_aodvSocket(&info,aodv_recvlen); (void)sigsetmask(omask); }}/* * called when we receive an aodv packet * determines type and calls method to take care of it */static void accept_aodvSocket(struct AodvPktInfo *info, int aodvlen) { //register struct ip *ip; register struct AodvMsg *aodvMsg; //struct iphdr *ipH; //char dbuf[25]; trace(TRACE_AODV_SOCKET,"received packet on aodvSocket"); if (aodvlen < sizeof(struct AodvMsg)) { log(LOG_WARNING, FALSE, "IP data field too short (%u bytes) for AODV header, from %s", aodvlen, inet_fmt_n(info->src, s1)); return; } trace(TRACE_AODV_SOCKET, "accept_aodvSocket:src=%s" ,inet_fmt_n(info->src, s1)); aodvMsg = (struct AodvMsg *)(aodv_recv_buf); trace(TRACE_AODV_SOCKET, "Received message type:%u for AODV header, from %s, to %s", aodvMsg->type, inet_fmt_n(info->src, s1), inet_fmt_n(info->dest, s2)); switch (aodvMsg->type) { case AODV_RREQ: trace(TRACE_METRIC,"r RREQ"); if(rebootTime==0){ receiveRREQ(info, (struct RREQ *)(aodvMsg)); }else{ trace(TRACE_AODV_SOCKET|TRACE_RREQ ,"dropping RREQ because during reboot"); } break; case AODV_RREP: //moved to receiveRREP so could //differeniate between rrep and hello //trace(TRACE_METRIC,"r RREP"); receiveRREP(info, (struct RREP *)(aodvMsg)); break; case AODV_RERR: trace(TRACE_METRIC,"r RERR"); if(rebootTime==0){ receiveRERR(ntohl(info->src), (char *)(aodvMsg)); }else{ trace(TRACE_AODV_SOCKET|TRACE_RERR ,"dropping RERR because during reboot"); } break; default: trace(TRACE_AODV_SOCKET, "ignore unknown AODV message type %u from %s", aodvMsg->type, inet_fmt_n(info->src, s1)); /* trace(TRACE_AODV_SOCKET, "checking message for iphdr"); ipH = (struct iphdr *)(aodv_recv_buf); trace(TRACE_AODV_SOCKET, "ipH->saddr=%s",inet_fmt_n(ipH->saddr,s1)); trace(TRACE_AODV_SOCKET, "ipH->daddr=%s",inet_fmt_n(ipH->daddr,s1)); //check that dest isn't broadcast sprintf(dbuf,"%s",inet_fmt_n(ipH->daddr,s1)); if(strstr(dbuf,"255")==NULL){ //if have active route update lifetime if(routeUsed(ipH->daddr)==FALSE){ //if don't have an active route //create RERR trace(TRACE_DEMO,"received message to (%s) NO ROUTE" ,inet_fmt_n(ipH->daddr,s1)); generateRERR(ipH->daddr); } }*/ break; }}/* * Set/reset the IP_HDRINCL option */void k_hdr_include(int socket, int bool) {#ifdef IP_HDRINCL if (setsockopt(socket, IPPROTO_IP, IP_HDRINCL, (char *)&bool, sizeof(bool)) < 0){ log(LOG_ERR, FALSE, "setsockopt IP_HDRINCL %u", bool); }#endif}/* * Set the socket receiving buffer. `bufsize` is the preferred size, * `minsize` is the smallest acceptable size. */void k_set_rcvbuf(int socket, int bufsize, int minsize) { int delta = bufsize / 2; int iter = 0; /* * Set the socket buffer. If we can't set it as large as we * want, search around to try to find the highest acceptable * value. The highest acceptable value being smaller than * minsize is a fatal error. */ if (setsockopt(socket, SOL_SOCKET, SO_RCVBUF, (char *)&bufsize, sizeof(bufsize)) < 0) { bufsize -= delta; while (1) { iter++; if (delta > 1){ delta /= 2; } if (setsockopt(socket, SOL_SOCKET, SO_RCVBUF, (char *)&bufsize, sizeof(bufsize)) < 0) { bufsize -= delta; } else { if (delta < 1024) break; bufsize += delta; } } if (bufsize < minsize) { log(LOG_ERR, FALSE, "OS-allowed buffer size %u < app min %u", bufsize, minsize); /*NOTREACHED*/ } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -