/* Serval Distributed Numbering Architecture (DNA) Copyright (C) 2010 Paul Gardner-Stephen 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "mphlr.h" char *batman_socket=NULL; char *batman_peerfile=NULL; int peer_count=0; struct in_addr peers[MAX_PEERS]; struct in_addr nominated_peers[256]; int nom_peer_count=0; int additionalPeer(char *peer) { struct in_addr pa; if (nom_peer_count>255) return setReason("Too many peers. You can only nominate 255 peers in this version."); pa.s_addr=inet_addr(peer); if (pa.s_addr==INADDR_NONE) return setReason("Invalid peer address specified."); nominated_peers[nom_peer_count++]=pa; return 0; } int getBroadcastAddresses(struct in_addr peers[],int *peer_count,int peer_max){ /* The Android ndk doesn't have ifaddrs.h, so we have to use the netlink interface. However, netlink is only available on Linux, so for BSD systems, e.g., Mac, we need to use the ifaddrs method. Also, ifaddrs will work on non-linux systems which is considered critical. */ #ifdef HAVE_LINUX_NETLINK_H // Ask for the address information. struct { struct nlmsghdr netlinkHeader; struct ifaddrmsg msg; }addrRequest; char buff[16384]; int netsock; size_t bytesRead; struct nlmsghdr *hdr; if (debug>1) fprintf(stderr,"Reading broadcast addresses\n"); netsock = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); memset(&addrRequest, 0, sizeof(addrRequest)); addrRequest.netlinkHeader.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT; addrRequest.netlinkHeader.nlmsg_type = RTM_GETADDR; addrRequest.netlinkHeader.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(addrRequest))); addrRequest.msg.ifa_family = AF_INET; addrRequest.msg.ifa_index = 0; // All interfaces. while (send(netsock, &addrRequest, addrRequest.netlinkHeader.nlmsg_len, 0)==EINTR); while(1){ while((bytesRead = recv(netsock, buff, sizeof(buff), 0))==EINTR); if (bytesRead<=0) break; for (hdr = (struct nlmsghdr*)buff; NLMSG_OK(hdr, (size_t)bytesRead); hdr = NLMSG_NEXT(hdr, bytesRead)) { switch (hdr->nlmsg_type) { case NLMSG_DONE: return 0; case NLMSG_ERROR: return -1; case RTM_NEWADDR: { struct ifaddrmsg* address = (struct ifaddrmsg*)(NLMSG_DATA(hdr)); struct rtattr* rta = IFA_RTA(address); size_t ifaPayloadLength = IFA_PAYLOAD(hdr); while (RTA_OK(rta, ifaPayloadLength)) { if (rta->rta_type == IFA_BROADCAST && address->ifa_family == AF_INET) { struct in_addr *addr=(struct in_addr *)RTA_DATA(rta); peers[(*peer_count)++].s_addr=addr->s_addr; } rta = RTA_NEXT(rta, ifaPayloadLength); } } break; } } } #else #ifdef HAVE_IFADDRS_H struct ifaddrs *ifaddr,*ifa; int family, s; char host[NI_MAXHOST]; if (getifaddrs(&ifaddr) == -1) { perror("getifaddr()"); return WHY("getifaddrs() failed"); } for (ifa=ifaddr;ifa!=NULL;ifa=ifa->ifa_next) { family=ifa->ifa_addr->sa_family; switch(family) { case AF_INET: /* Add our local address and computed broadcast address to the list of peers. XXX - ifa->ifa_broadaddr should give us the broadcast address, but doesn't seem to on mac osx. So we have resorted computing the normal (ceiling) broadcast address. */ peers[(*peer_count)++].s_addr=((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr; { struct sockaddr_in broadcast; unsigned int local=(((struct sockaddr_in *)(ifa->ifa_addr))->sin_addr.s_addr); unsigned int netmask=(((struct sockaddr_in *)(ifa->ifa_netmask))->sin_addr.s_addr); peers[(*peer_count)++].s_addr=local|~netmask; } break; } } #endif #endif return 0; } int getPeerList() { /* Generate the list of known peers. If using BATMAN layer 3, this needs to be the list of exact IP addresses of the peers, as we cannot reliably broadcast. Once BATMAN Advanced is available, we will be able to do that. In the mean time, we need to query BATMANd to find the known list of peers. This is not quite as easy as we might wish. */ int i; peer_count=0; /* Add user specified peers */ for(i=0;i1) fprintf(stderr,"Sending packet to peer #%d\n",i); ret=sendto(sock,packet,packet_len,0,(struct sockaddr *)&peer_addr,sizeof(peer_addr)); if (ret1) fprintf(stderr,"Sent request to peer %s\n",inet_ntoa(peer_addr.sin_addr)); n++; /* If sending to only one peer, return now */ if (method==i) break; } } else if (debug>1) fprintf(stderr,"Peer %s has already replied, so not sending again.\n", inet_ntoa(peer_addr.sin_addr)); if (debug) fprintf(stderr,"Sent request to %d peers.\n",n); return 0; }