/* Packet.cpp Reverse ARP Daemon for Alasin Copyright (C) 2003 Mike Saywell Southampton Open Wireless Network, http://www.sown.org.uk ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ As it's name suggests this class deals with the Aladin protocol. It is used to generate, send and receive packets. ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ 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. */ #include "Packet.h" Packet::Packet(u_char t) { this->type = t; this->network = 0; this->netmask = 0; } void Packet::prnType(char * type) { if (this->type == ALADIN_INVALID) { strcpy(type, "INVALID"); } else if (this->type == ALADIN_HELLO) { strcpy(type, "HELLO"); } else if (this->type == ALADIN_REQUEST) { strcpy(type, "REQUEST"); } else if (this->type == ALADIN_REPLY) { strcpy(type, "REPLY"); } else if (this->type == ALADIN_ACK) { strcpy(type, "ACK"); } } int Packet::genPkt(u_char* msg) { u_char* data = msg; if ((this->type == ALADIN_HELLO) || (this->type == ALADIN_REQUEST) || (this->type == ALADIN_REPLY) || (this->type == ALADIN_ACK)) { data[0] = this->type; } else { data[0] = ALADIN_INVALID; } // If it's a REPLY copy in the network & netmask if(this->type == ALADIN_REPLY) { u_int32_t* pNetwork = (u_int32_t*) (data+4); u_int32_t* pNetmask = (u_int32_t*) (data+8); *pNetwork = this->network; *pNetmask = this->netmask; } } int Packet::parse(u_char* raw, Packet* p) { p->reset(); p->setType(raw[0]); if(p->getType() == ALADIN_REPLY) { u_int32_t* pNetwork = (u_int32_t*) (raw+4); u_int32_t* pNetmask = (u_int32_t*) (raw+8); struct in_addr* tmp = new struct in_addr; tmp->s_addr = *pNetwork; p->setNetwork(tmp); tmp->s_addr = *pNetmask; p->setNetmask(tmp); delete tmp; } return 1; } int Packet::send(Packet* p, int if_id) { int ret_val = 1; // The packet u_char* msg = new u_char[ALADIN_LEN]; memset(msg, 0, ALADIN_LEN); struct sockaddr_ll* to = new struct sockaddr_ll; memset(to, 0, sizeof(struct sockaddr_ll)); to->sll_family = AF_PACKET; to->sll_ifindex = if_id; to->sll_protocol = htons(ALADIN_PROTOCOL); memset(to->sll_addr, 255, ETHER_ADDR_LEN); to->sll_halen = ETHER_ADDR_LEN; p->genPkt(msg); int sock; if ((sock = socket(PF_PACKET, SOCK_DGRAM, htons(ALADIN_PROTOCOL))) == -1) { perror("Packet::send():socket"); ret_val = -1; } else if (sendto(sock, msg, ALADIN_LEN, 0, (struct sockaddr*) to, sizeof(struct sockaddr_ll)) == -1) { perror("Packet::send():sendto"); ret_val = -1; } close(sock); // Cleanup delete to; delete msg; return ret_val; } int Packet::receive(Packet* p, int if_id, int timeout) { int ret_val = 0; int sock; p->reset(); if ((sock = socket(PF_PACKET, SOCK_DGRAM, htons(ALADIN_PROTOCOL))) == -1) { perror("Packet::receive():socket"); return -1; } struct sockaddr_ll* from = new struct sockaddr_ll; memset(from, 0, sizeof(struct sockaddr_ll)); from->sll_family = AF_PACKET; from->sll_protocol = htons(ALADIN_PROTOCOL); from->sll_ifindex = if_id; memset(from->sll_addr, 255, ETHER_ADDR_LEN); from->sll_halen = ETHER_ADDR_LEN; if(bind(sock, (struct sockaddr*) from, sizeof(struct sockaddr_ll))) { cerr << " * Failed to bind on interface " << if_id << " : " << strerror(errno) << endl; delete from; return -1; } u_char* msg = new u_char[ALADIN_LEN]; fd_set rfds; // Wait on the socket FD_ZERO(&rfds); FD_SET(sock, &rfds); // Wait up to 'timeout' seconds struct timeval tv; tv.tv_sec = timeout; tv.tv_usec = 0; int i = select(sock+1, &rfds, NULL, NULL, &tv); if (i > 0) { socklen_t size = sizeof(struct sockaddr_ll); int test = 0; while (!test) { if (recvfrom(sock, msg, ALADIN_LEN, 0, (struct sockaddr*) from, &size) == -1) { perror("Packet::receive():recvfrom"); ret_val = -1; test = 1; } else { test = Packet::parse(msg, p); ret_val = 1; } } } close(sock); delete from; delete msg; return ret_val; } u_char Packet::getType() { return this->type; } void Packet::setType(u_char t) { this->type = t; } void Packet::reset() { this->type = ALADIN_INVALID; this->network = 0; this->netmask = 0; } void Packet::setNetwork(struct in_addr* net) { this->network = net->s_addr; } void Packet::setNetmask(struct in_addr* mask) { this->netmask = mask->s_addr; } u_int32_t Packet::getNetwork() { return this->network; } u_int32_t Packet::getNetmask() { return this->netmask; }