Exemple #1
0
int NS_CLASS locality(struct in_addr dest, unsigned int ifindex)
{

#ifndef NS_PORT
	if (gw_prefix) {
		if ((dest.s_addr & DEV_IFINDEX(ifindex).netmask.s_addr) ==
		    (DEV_IFINDEX(ifindex).ipaddr.s_addr & DEV_IFINDEX(ifindex).
		     netmask.s_addr))
			return HOST_ADHOC;
		else
			return HOST_INET;

	} else {
		struct hostent *hent;

		hent = gethostbyaddr(&dest, sizeof(struct in_addr), AF_INET);

		if (!hent) {
			switch (h_errno) {
			case HOST_NOT_FOUND:
				DEBUG(LOG_DEBUG, 0,
				      "RREQ for Non-Internet dest %s",
				      ip_to_str(dest));
				return HOST_UNKNOWN;
			default:
				DEBUG(LOG_DEBUG, 0, "Unknown DNS error");
				break;

			}
		} else
			return HOST_INET;
	}
#else
	char *dstnet = Address::instance().get_subnetaddr(dest.s_addr);
	char *subnet =
	    Address::instance().get_subnetaddr(DEV_NR(NS_DEV_NR).ipaddr.s_addr);
	DEBUG(LOG_DEBUG, 0, "myaddr=%d, dest=%d dstnet=%s subnet=%s",
	      DEV_NR(NS_DEV_NR).ipaddr.s_addr, dest.s_addr, dstnet, subnet);
	if (subnet != NULL) {
		if (dstnet != NULL) {
			if (strcmp(dstnet, subnet) != 0) {
				delete[]dstnet;
				return HOST_INET;
			}
			delete[]dstnet;
		}
		delete[]subnet;
	}
	assert(dstnet == NULL);
	return HOST_UNKNOWN;
#endif
	return HOST_UNKNOWN;
}
void NS_CLASS local_repair_timeout(void *arg)
{
    rt_table_t *rt;
    struct in_addr rerr_dest;
    RERR *rerr = NULL;

    rt = (rt_table_t *) arg;

    if (!rt)
        return;

    rerr_dest.s_addr = AODV_BROADCAST;	/* Default destination */

    /* Unset the REPAIR flag */
    rt->flags &= ~RT_REPAIR;

#ifndef NS_PORT
    nl_send_del_route_msg(rt->dest_addr, rt->next_hop, rt->hcnt);
#endif
    /* Route should already be invalidated. */

    if (rt->nprec) {

        rerr = rerr_create(0, rt->dest_addr, rt->dest_seqno);

        if (rt->nprec == 1) {
            rerr_dest = FIRST_PREC(rt->precursors)->neighbor;

            aodv_socket_send((AODV_msg *) rerr, rerr_dest,
                             RERR_CALC_SIZE(rerr), 1,
                             &DEV_IFINDEX(rt->ifindex));
        } else {
            int i;

            for (i = 0; i < MAX_NR_INTERFACES; i++) {
                if (!DEV_NR(i).enabled)
                    continue;
                aodv_socket_send((AODV_msg *) rerr, rerr_dest,
                                 RERR_CALC_SIZE(rerr), 1,
                                 &DEV_NR(i));
            }
        }
        DEBUG(LOG_DEBUG, 0, "Sending RERR about %s to %s",
              ip_to_str(rt->dest_addr), ip_to_str(rerr_dest));
    }
    precursor_list_destroy(rt);

    /* Purge any packets that may be queued */
    /* packet_queue_set_verdict(rt->dest_addr, PQ_DROP); */

    rt->rt_timer.handler = &NS_CLASS route_delete_timeout;
    timer_set_timeout(&rt->rt_timer, DELETE_PERIOD);

    DEBUG(LOG_DEBUG, 0, "%s removed in %u msecs",
          ip_to_str(rt->dest_addr), DELETE_PERIOD);
}
Exemple #3
0
void NS_CLASS rrep_send(RREP * rrep, rt_table_t * rev_rt,
			rt_table_t * fwd_rt, int size)
{
	u_int8_t rrep_flags = 0;
	struct in_addr dest;

	if (!rev_rt) {
		DEBUG(LOG_WARNING, 0, "Can't send RREP, rev_rt = NULL!");
		return;
	}

	dest.s_addr = rrep->dest_addr;

	/* Check if we should request a RREP-ACK */
	if ((rev_rt->state == VALID && rev_rt->flags & RT_UNIDIR) ||
	    (rev_rt->hcnt == 1 && unidir_hack)) {
		rt_table_t *neighbor = rt_table_find(rev_rt->next_hop);

		if (neighbor && neighbor->state == VALID
		    && !neighbor->ack_timer.used) {
			/* If the node we received a RREQ for is a neighbor we are
			   probably facing a unidirectional link... Better request a
			   RREP-ack */
			rrep_flags |= RREP_ACK;
			neighbor->flags |= RT_UNIDIR;

			/* Must remove any pending hello timeouts when we set the
			   RT_UNIDIR flag, else the route may expire after we begin to
			   ignore hellos... */
			timer_remove(&neighbor->hello_timer);
			neighbor_link_break(neighbor);

			DEBUG(LOG_DEBUG, 0, "Link to %s is unidirectional!",
			      ip_to_str(neighbor->dest_addr));

			timer_set_timeout(&neighbor->ack_timer, NEXT_HOP_WAIT);
		}
	}

	DEBUG(LOG_DEBUG, 0, "Sending RREP to next hop %s about %s->%s",
	      ip_to_str(rev_rt->next_hop), ip_to_str(rev_rt->dest_addr),
	      ip_to_str(dest));

	aodv_socket_send((AODV_msg *) rrep, rev_rt->next_hop, size, MAXTTL,
			 &DEV_IFINDEX(rev_rt->ifindex));

	/* Update precursor lists */
	if (fwd_rt) {
		precursor_add(fwd_rt, rev_rt->next_hop);
		precursor_add(rev_rt, fwd_rt->next_hop);
	}

	if (!llfeedback && optimized_hellos)
		hello_start();
}
Exemple #4
0
void NS_CLASS rrep_forward(RREP * rrep, int size, rt_table_t * rev_rt,
			   rt_table_t * fwd_rt, int ttl)
{
	/* Sanity checks... */
	if (!fwd_rt || !rev_rt) {
		DEBUG(LOG_WARNING, 0,
		      "Could not forward RREP because of NULL route!");
		return;
	}

	if (!rrep) {
		DEBUG(LOG_WARNING, 0, "No RREP to forward!");
		return;
	}

	DEBUG(LOG_DEBUG, 0, "Forwarding RREP to %s",
	      ip_to_str(rev_rt->next_hop));

	/* Here we should do a check if we should request a RREP_ACK,
	   i.e we suspect a unidirectional link.. But how? */
	if (0) {
		rt_table_t *neighbor;

		/* If the source of the RREP is not a neighbor we must find the
		   neighbor (link) entry which is the next hop towards the RREP
		   source... */
		if (rev_rt->dest_addr.s_addr != rev_rt->next_hop.s_addr)
			neighbor = rt_table_find(rev_rt->next_hop);
		else
			neighbor = rev_rt;

		if (neighbor && !neighbor->ack_timer.used) {
			/* If the node we received a RREQ for is a neighbor we are
			   probably facing a unidirectional link... Better request a
			   RREP-ack */
			rrep->a = 1;
			neighbor->flags |= RT_UNIDIR;

			timer_set_timeout(&neighbor->ack_timer, NEXT_HOP_WAIT);
		}
	}

	rrep = (RREP *) aodv_socket_queue_msg((AODV_msg *) rrep, size);
	rrep->hcnt = fwd_rt->hcnt;	/* Update the hopcount */

	aodv_socket_send((AODV_msg *) rrep, rev_rt->next_hop, size, ttl,
			 &DEV_IFINDEX(rev_rt->ifindex));

	precursor_add(fwd_rt, rev_rt->next_hop);
	precursor_add(rev_rt, fwd_rt->next_hop);

	rt_table_update_timeout(rev_rt, ACTIVE_ROUTE_TIMEOUT);
}
Exemple #5
0
void NS_CLASS local_repair_timeout(void *arg)
{
    rt_table_t *rt;
    u_int32_t rerr_dest = AODV_BROADCAST;
    RERR *rerr = NULL;

    rt = (rt_table_t *) arg;

    if (!rt)
	return;

    /* Unset the REPAIR flag */
    rt->flags &= ~RT_REPAIR;

    rt->rt_timer.handler = &NS_CLASS route_delete_timeout;
    timer_set_timeout(&rt->rt_timer, DELETE_PERIOD);

    DEBUG(LOG_DEBUG, 0, "%s removed in %u msecs",
	  ip_to_str(rt->dest_addr), DELETE_PERIOD);

    /* Route should already be invalidated. */

    if (rt->nprec) {

	rerr = rerr_create(0, rt->dest_addr, rt->dest_seqno);

	if (rt->nprec == 1) {
	    rerr_dest = FIRST_PREC(rt->precursors)->neighbor;

	    aodv_socket_send((AODV_msg *) rerr, rerr_dest, 
			     RERR_CALC_SIZE(rerr), 1,
			     &DEV_IFINDEX(rt->ifindex));
	} else {
	    int i;

	    for (i = 0; i < MAX_NR_INTERFACES; i++) {
		if (!DEV_NR(i).enabled)
		    continue;
		aodv_socket_send((AODV_msg *) rerr, rerr_dest,
				 RERR_CALC_SIZE(rerr), 1, &DEV_NR(i));
	    }
	}
	DEBUG(LOG_DEBUG, 0, "Sending RERR about %s to %s",
	      ip_to_str(rt->dest_addr), ip_to_str(rerr_dest));
    }
    precursor_list_destroy(rt);
}
Exemple #6
0
static void packet_input(int fd)
#endif
{
    rt_table_t *fwd_rt, *rev_rt, *next_hop_rt = NULL;
    struct in_addr dest_addr, src_addr;
    u_int8_t rreq_flags = 0;
    unsigned int ifindex;
    struct ip_data *ipd = NULL;
    int pkt_flags = 0;

#ifdef NS_PORT
    ifindex = NS_IFINDEX;	/* Always use ns interface */
    fwd_rt = NULL;		/* For broadcast we provide no next hop */
    ipd = NULL;			/* No ICMP messaging */

    struct hdr_cmn *ch = HDR_CMN(p);
    struct hdr_ip *ih = HDR_IP(p);

    src_addr.s_addr = ih->saddr();
    dest_addr.s_addr = ih->daddr();

    /* If this is a TCP packet and we don't have a route, we should
       set the gratuituos flag in the RREQ. */
    if (ch->ptype() == PT_TCP) {
	rreq_flags |= RREQ_GRATUITOUS;
    }
#else
    int status;
    char buf[sizeof(struct nlmsghdr)+sizeof(ipq_packet_msg_t)+BUFSIZE];
    char *dev_name;
    ipq_packet_msg_t *pkt;
    struct iphdr *ip;
    struct udphdr *udp;
    struct icmphdr *icmp = NULL;

    status =  ipq_read(h, buf, sizeof(buf), -1);
    
    if (status < 0) {
	DEBUG(LOG_DEBUG, 0, "%s", ipq_errstr());
	ipq_perror(NULL);
	return;
    }

    if (ipq_message_type(buf) == NLMSG_ERROR) {
	fprintf(stderr,
		"ERROR packet_input: Check that the ip_queue.o module is loaded.\n");
	die(h);
    }

    pkt = ipq_get_packet(buf);

#ifdef DEBUG_PACKET
    DEBUG(LOG_DEBUG, 0, "Protocol %u indev=%s outdev=%s\n",
	  pkt->hw_protocol, pkt->indev_name, pkt->outdev_name);
#endif

    if (pkt->hook == 0)
	dev_name = pkt->indev_name;
    else if (pkt->hook == 3)
	dev_name = pkt->outdev_name;
    else
	dev_name = NULL;

    /* We know from kaodv.c that this is an IP packet */
    ip = (struct iphdr *) pkt->payload;

    dest_addr.s_addr = ip->daddr;
    src_addr.s_addr = ip->saddr;

    switch (ip->protocol) {
	/* Don't process AODV control packets (UDP on port 654). They
	   are accounted for on the aodv socket */
    case IPPROTO_UDP:
	udp = (struct udphdr *) ((char *) ip + (ip->ihl << 2));
	if (ntohs(udp->dest) == AODV_PORT || ntohs(udp->source) == AODV_PORT)
	    goto accept;
	break;
	/* If this is a TCP packet and we don't have a route, we should
	   set the gratuituos flag in the RREQ. */
    case IPPROTO_TCP:
	rreq_flags |= RREQ_GRATUITOUS;
	break;
	/* We set the gratuitous flag also on ICMP ECHO requests, since
	   the destination will also need a route back for the reply... */
    case IPPROTO_ICMP:
	icmp = (struct icmphdr *) ((char *) ip + (ip->ihl << 2));
	if (icmp->type == ICMP_ECHO)
	    rreq_flags |= RREQ_GRATUITOUS;
#ifdef DEBUG_PACKET
	DEBUG(LOG_INFO, 0, "setting G flag for RREQ to %s",
	      ip_to_str(dest_addr));
#endif

	break;
#ifdef CONFIG_GATEWAY
    case IPPROTO_MIPE:
	if (internet_gw_mode) {
	    
	    ip = ip_pkt_decapsulate(ip);

	    if (ip == NULL) {
	      DEBUG(LOG_ERR, 0, "Decapsulation failed...");
	      exit(-1);
	    }
	    pkt_flags |= PKT_DEC;
	}
	break;
#endif /* CONFIG_GATEWAY */
    }

#ifdef DEBUG_PACKET
    DEBUG(LOG_INFO, 0, "pkt to %s", ip_to_str(dest_addr));
#endif

    if (dev_name) {
	ifindex = name2index(dev_name);
	if (ifindex < 0) {
	    DEBUG(LOG_ERR, 0, "name2index error!");
	    return;
	}
    } else
	ifindex = 0;
#endif				/* NS_PORT */

    /* If the packet is not interesting we just let it go through... */
    if (dest_addr.s_addr == AODV_BROADCAST ||
	dest_addr.s_addr == DEV_IFINDEX(ifindex).broadcast.s_addr) {
#ifdef NS_PORT
	/* Limit Non AODV broadcast packets (Rolf Winter
	 * <[email protected]). */
	ih->ttl() = ih->ttl() - 1;                
       
	if(ih->ttl() < 1)        
	    Packet::free(p);                
	else
	    sendPacket(p, dest_addr, 0.0);
	return;
#else
	goto accept;
#endif
    }
    
    /* Find the entry of the neighboring node and the destination  (if any). */
    rev_rt = rt_table_find(src_addr);
    fwd_rt = rt_table_find(dest_addr);

#ifdef CONFIG_GATEWAY
    /* Check if we have a route and it is an Internet destination (Should be
     * encapsulated and routed through the gateway). */
    if (fwd_rt && (fwd_rt->state == VALID) && 
	(fwd_rt->flags & RT_INET_DEST)) {
	/* The destination should be relayed through the IG */

	rt_table_update_timeout(fwd_rt, ACTIVE_ROUTE_TIMEOUT);
#ifdef NS_PORT
	p = pkt_encapsulate(p, fwd_rt->next_hop);

	if (p == NULL) {
	    DEBUG(LOG_ERR, 0, "IP Encapsulation failed!");
	   return;	    
	}
	/* Update pointers to headers */
	ch = HDR_CMN(p);
	ih = HDR_IP(p);
#else
	ip = ip_pkt_encapsulate(ip, fwd_rt->next_hop, BUFSIZE);

	if (ip == NULL) {
	    DEBUG(LOG_ERR, 0, "Minimal IP Encapsulation failed!");
	    exit(-1);	    
	}
#endif
	dest_addr = fwd_rt->next_hop;
	fwd_rt = rt_table_find(dest_addr);
	pkt_flags |= PKT_ENC;
    }
#endif /* CONFIG_GATEWAY */

    /* UPDATE TIMERS on active forward and reverse routes...  */

    /* When forwarding a packet, we update the lifetime of the
       destination's routing table entry, as well as the entry for the
       next hop neighbor (if not the same). AODV draft 10, section
       6.2. */
    if (fwd_rt && fwd_rt->state == VALID &&
	dest_addr.s_addr != DEV_IFINDEX(ifindex).ipaddr.s_addr) {

	rt_table_update_timeout(fwd_rt, ACTIVE_ROUTE_TIMEOUT);

	next_hop_rt = rt_table_find(fwd_rt->next_hop);
	
	if (next_hop_rt && next_hop_rt->state == VALID && 
	    next_hop_rt->dest_addr.s_addr != fwd_rt->dest_addr.s_addr)
	    rt_table_update_timeout(next_hop_rt, ACTIVE_ROUTE_TIMEOUT);

    }
    /* Also update the reverse route and reverse next hop along the
       path back, since routes between originators and the destination
       are expected to be symmetric. */
    if (rev_rt && rev_rt->state == VALID) {
	
	rt_table_update_timeout(rev_rt, ACTIVE_ROUTE_TIMEOUT);

	next_hop_rt = rt_table_find(rev_rt->next_hop);

	if (next_hop_rt && next_hop_rt->state == VALID &&
	    rev_rt && next_hop_rt->dest_addr.s_addr != rev_rt->dest_addr.s_addr)
	    rt_table_update_timeout(next_hop_rt, ACTIVE_ROUTE_TIMEOUT);

	/* Update HELLO timer of next hop neighbor if active */   
	if (!llfeedback && next_hop_rt->hello_timer.used) {
	    struct timeval now;
	
	    gettimeofday(&now, NULL);
	    hello_update_timeout(next_hop_rt, &now, 
				 ALLOWED_HELLO_LOSS * HELLO_INTERVAL);
	}
    }

    /* OK, the timeouts have been updated. Now see if either: 1. The
       packet is for this node -> ACCEPT. 2. The packet is not for this
       node -> Send RERR (someone want's this node to forward packets
       although there is no route) or Send RREQ. */

    /* If the packet is destined for this node, then just accept it. */
    if (memcmp(&dest_addr, &DEV_IFINDEX(ifindex).ipaddr, 
	       sizeof(struct in_addr)) == 0) {

#ifdef NS_PORT
	ch->size() -= IP_HDR_LEN;    // cut off IP header size 4/7/99 -dam
	target_->recv(p, (Handler*)0);
	p = 0;
	return;
#else
	goto accept;
#endif
    }
    if (!fwd_rt || fwd_rt->state == INVALID ||
	(fwd_rt->hcnt == 1 && (fwd_rt->flags & RT_UNIDIR))) {

	/* Check if the route is marked for repair or is INVALID. In
	 * that case, do a route discovery. */
	if (fwd_rt && (fwd_rt->flags & RT_REPAIR))
	    goto route_discovery;

	/* If a packet is received on the NF_IP_PRE_ROUTING hook,
	   i.e. inbound on the interface and we don't have a route to
	   the destination, we should send an RERR to the source and
	   then drop the package... */
	/* NF_IP_PRE_ROUTING = 0 */
#ifdef NS_PORT
#define PACKET_IS_INBOUND ch->direction() == hdr_cmn::UP
#else
#define PACKET_IS_INBOUND pkt->hook == 0
#endif

	if (PACKET_IS_INBOUND) {

	    struct in_addr rerr_dest;
	    RERR *rerr;
#ifdef NS_PORT
	    struct in_addr nh;
	    nh.s_addr = ch->prev_hop_;
	    
	    DEBUG(LOG_DEBUG, 0,
		  "No route, src=%s dest=%s prev_hop=%s - DROPPING!",
		  ip_to_str(src_addr), ip_to_str(dest_addr),
		  ip_to_str(nh));
#endif
	    if (fwd_rt) {
		rerr = rerr_create(0, fwd_rt->dest_addr,
				   fwd_rt->dest_seqno);

		rt_table_update_timeout(fwd_rt, DELETE_PERIOD);
	    } else
		rerr = rerr_create(0, dest_addr, 0);
	    
	    DEBUG(LOG_DEBUG, 0, "Sending RERR to prev hop %s for unknown dest %s", ip_to_str(src_addr), ip_to_str(dest_addr));
	    
	    /* Unicast the RERR to the source of the data transmission
	     * if possible, otherwise we broadcast it. */
	    
	    if (rev_rt && rev_rt->state == VALID)
		rerr_dest = rev_rt->next_hop;
	    else
		rerr_dest.s_addr = AODV_BROADCAST;

	    aodv_socket_send((AODV_msg *) rerr, rerr_dest,
			     RERR_CALC_SIZE(rerr), 1, &DEV_IFINDEX(ifindex));

	    if (wait_on_reboot) {
		DEBUG(LOG_DEBUG, 0, "Wait on reboot timer reset.");
		timer_set_timeout(&worb_timer, DELETE_PERIOD);
	    }
#ifdef NS_PORT
	    /* DEBUG(LOG_DEBUG, 0, "Dropping pkt uid=%d", ch->uid()); */
	    drop(p, DROP_RTR_NO_ROUTE);
#else
	    status = ipq_set_verdict(h, pkt->packet_id, NF_DROP, 0, NULL);
	    
	    if (status < 0)
		die(h);
#endif
	    return;
	}

      route_discovery:
	/* Buffer packets... Packets are queued by the ip_queue.o
	   module already. We only need to save the handle id, and
	   return the proper verdict when we know what to do... */

#ifdef NS_PORT
	packet_queue_add(p, dest_addr);
#else
	packet_queue_add(pkt->packet_id, dest_addr, ip);
	
#ifdef CONFIG_GATEWAY
	/* In gateway mode we handle packets in userspace */
	ipq_set_verdict(h, pkt->packet_id, NF_DROP, 0, NULL);
#endif
	/* Already seeking the destination? Then do not allocate any
	   memory or generate a RREQ. */
	if (seek_list_find(dest_addr))
	    return;

	/* If the request is generated locally by an application, we save
	   the IP header + 64 bits of data for sending an ICMP Destination
	   Host Unreachable in case we don't find a route... */
	if (src_addr.s_addr == DEV_IFINDEX(ifindex).ipaddr.s_addr && ip &&
	    pkt->data_len >= (ip->ihl << 2) + 8) {
	    ipd = (struct ip_data *) malloc(sizeof(struct ip_data));
	    if (ipd == NULL) {
		perror("Malloc for IP data failed!");
		exit(-1);
	    }
	    /* IP header + 64 bits data (8 bytes) */
	    ipd->len = (ip->ihl << 2) + 8;
	    memcpy(ipd->data, ip, ipd->len);
	} else
	    ipd = NULL;
#endif
	if (fwd_rt && (fwd_rt->flags & RT_REPAIR))
	    rreq_local_repair(fwd_rt, src_addr, ipd);
	else
	    rreq_route_discovery(dest_addr, rreq_flags, ipd);

	return;

    } else {

#ifdef NS_PORT
	/* DEBUG(LOG_DEBUG, 0, "Sending pkt uid=%d", ch->uid()); */
	sendPacket(p, fwd_rt->next_hop, 0.0);
#else	
      accept:

	if (pkt_flags & PKT_ENC || (pkt_flags & PKT_DEC))
	    status = ipq_set_verdict(h, pkt->packet_id, NF_ACCEPT, 
				     ntohs(ip->tot_len), (unsigned char *)ip);
	else
	    status = ipq_set_verdict(h, pkt->packet_id, NF_ACCEPT, 0, NULL);
	
	if (status < 0)
	    die(h);

#endif
	/* When forwarding data, make sure we are sending HELLO messages */
	gettimeofday(&this_host.fwd_time, NULL);

	if (!llfeedback && optimized_hellos)
	    hello_start();
    }
}
Exemple #7
0
void host_init(char *ifname)
{
    struct sockaddr_in *ina;
    char buf[1024], tmp_ifname[IFNAMSIZ],
	ifnames[(IFNAMSIZ + 1) * MAX_NR_INTERFACES], *iface;
    struct ifconf ifc;
    struct ifreq ifreq, *ifr;
    int i, iw_sock, if_sock = 0;

    memset(&this_host, 0, sizeof(struct host_info));
    memset(dev_indices, 0, sizeof(unsigned int) * MAX_NR_INTERFACES);

    if (!ifname) {
	/* No interface was given... search for first wireless. */
	iw_sock = socket(PF_INET, SOCK_DGRAM, 0);
	ifc.ifc_len = sizeof(buf);
	ifc.ifc_buf = buf;
	if (ioctl(iw_sock, SIOCGIFCONF, &ifc) < 0) {
	    fprintf(stderr, "Could not get wireless info\n");
	    exit(-1);
	}
	ifr = ifc.ifc_req;
	for (i = ifc.ifc_len / sizeof(struct ifreq); i >= 0; i--, ifr++) {
	    struct iwreq req;

	    strcpy(req.ifr_name, ifr->ifr_name);
	    if (ioctl(iw_sock, SIOCGIWNAME, &req) >= 0) {
		strcpy(tmp_ifname, ifr->ifr_name);
		break;
	    }
	}
	/* Did we find a wireless interface? */
	if (!strlen(tmp_ifname)) {
	    fprintf(stderr, "\nCould not find a wireless interface!\n");
	    fprintf(stderr, "Use -i <interface> to override...\n\n");
	    exit(-1);
	}
	strcpy(ifreq.ifr_name, tmp_ifname);
	if (ioctl(iw_sock, SIOCGIFINDEX, &ifreq) < 0) {
	    alog(LOG_ERR, errno, __FUNCTION__,
		 "Could not get index of %s", tmp_ifname);
	    close(if_sock);
	    exit(-1);
	}
	close(iw_sock);

	ifname = tmp_ifname;

	alog(LOG_NOTICE, 0, __FUNCTION__,
	     "Attaching to %s, override with -i <if1,if2,...>.", tmp_ifname);
    }

    strcpy(ifnames, ifname);

    /* Intitialize the local sequence number an rreq_id to zero */
    this_host.seqno = 1;
    this_host.rreq_id = 0;

    /* Zero interfaces enabled so far... */
    this_host.nif = 0;

    gettimeofday(&this_host.bcast_time, NULL);

    /* Find the indices of all interfaces to broadcast on... */
    if_sock = socket(AF_INET, SOCK_DGRAM, 0);

    iface = strtok(ifname, ",");

    /* OK, now lookup interface information, and store it... */
    do {
	strcpy(ifreq.ifr_name, iface);
	if (ioctl(if_sock, SIOCGIFINDEX, &ifreq) < 0) {
	    alog(LOG_ERR, errno, __FUNCTION__, "Could not get index of %s",
		 iface);
	    close(if_sock);
	    exit(-1);
	}
	this_host.devs[this_host.nif].ifindex = ifreq.ifr_ifindex;

	dev_indices[this_host.nif++] = ifreq.ifr_ifindex;

	strcpy(DEV_IFINDEX(ifreq.ifr_ifindex).ifname, iface);

	/* Get IP-address of interface... */
	ina = get_if_info(iface, SIOCGIFADDR);

	if (ina == NULL)
	    exit(-1);

	DEV_IFINDEX(ifreq.ifr_ifindex).ipaddr = ina->sin_addr;

	/* Get netmask of interface... */
	ina = get_if_info(iface, SIOCGIFNETMASK);

	if (ina == NULL)
	    exit(-1);

	DEV_IFINDEX(ifreq.ifr_ifindex).netmask = ina->sin_addr;

	ina = get_if_info(iface, SIOCGIFBRDADDR);

	if (ina == NULL)
	    exit(-1);

	DEV_IFINDEX(ifreq.ifr_ifindex).broadcast = ina->sin_addr;

	DEV_IFINDEX(ifreq.ifr_ifindex).enabled = 1;

	if (this_host.nif >= MAX_NR_INTERFACES)
	    break;

    } while ((iface = strtok(NULL, ",")));

    close(if_sock);

    /* Load kernel modules */
    load_modules(ifnames);

    /* Enable IP forwarding and set other kernel options... */
    if (set_kernel_options() < 0) {
	fprintf(stderr, "Could not set kernel options!\n");
	exit(-1);
    }
}
Exemple #8
0
void
rrep_process(RREP * rrep, int rreplen, u_int32_t ip_src, u_int32_t ip_dst,
	     int ip_ttl, unsigned int ifindex)
{
    u_int32_t rrep_dest, rrep_orig, rrep_lifetime, rrep_seqno;
    rt_table_t *fwd_rt, *rev_rt;

    /* Convert to correct byte order on affeected fields: */
    rrep_dest = ntohl(rrep->dest_addr);
    rrep_orig = ntohl(rrep->orig_addr);
    rrep_seqno = ntohl(rrep->dest_seqno);
    rrep_lifetime = ntohl(rrep->lifetime);

    if (rreplen < RREP_SIZE) {
	log(LOG_WARNING, 0,
	    "rrep_process: IP data field too short (%u bytes)"
	    " from %s to %s", rreplen, ip_to_str(ip_src),
	    ip_to_str(ip_dst));
	return;
    }

    /* Ignore messages which aim to a create a route to one self */
    if (memcmp(&rrep_dest, &DEV_IFINDEX(ifindex).ipaddr, sizeof(u_int32_t)) == 0 &&
	memcmp(&rrep_orig, &DEV_IFINDEX(ifindex).ipaddr, sizeof(u_int32_t)) == 0)
	return;

    /* Check if this was a hello message... */
    if (ip_ttl == 1) {
	if (memcmp(&ip_src, &DEV_IFINDEX(ifindex).ipaddr, sizeof(u_int32_t)) != 0)
	    hello_process(rrep, rreplen, ifindex);
	return;
    }
#ifdef DEBUG
    log(LOG_DEBUG, 0, "RREP_process: from=%s about %s->%s",
	ip_to_str(ip_src), ip_to_str(rrep_orig), ip_to_str(rrep_dest));
    log_pkt_fields((AODV_msg *) rrep);
#endif

    /* When a node receives a RREP, it first increments the hop count in
       the RREP, to account for the extra hop */
    rrep->hcnt++;

    /* ---------- CHECK IF WE SHOULD MAKE A FORWARD ROUTE ------------
       We update or insert a forward route only if:

       (i) the Destination Sequence Number in the RREP is greater than
       the node's copy of the destination sequence number, or

       (ii) the sequence numbers are the same, but the route is no
       longer active or the Hop Count in RREP is smaller than the hop
       count in route table entry. */

    fwd_rt = rt_table_find(rrep_dest);

    if (fwd_rt == NULL) {
	/* We didn't have an existing entry, so we insert a new one. */
	fwd_rt = rt_table_insert(rrep_dest, ip_src, rrep->hcnt,
				 rrep_seqno, rrep_lifetime, FWD_ROUTE, ifindex);
    } else if ((rrep_seqno > fwd_rt->dest_seqno) ||
	       (((rrep_seqno == fwd_rt->dest_seqno) &&
		 IS_INFTY(fwd_rt->hcnt)) ||
		(fwd_rt->flags & UNIDIR) || (rrep->hcnt < fwd_rt->hcnt))) {
	fwd_rt = rt_table_update(fwd_rt, ip_src, rrep->hcnt,
				 rrep_seqno, rrep_lifetime, FWD_ROUTE);
    } else
	return;


    /* Check if this RREP was for us (i.e. we previously made a RREQ
       for this host). */
    if (memcmp(&rrep_orig, &DEV_IFINDEX(ifindex).ipaddr, sizeof(u_int32_t)) == 0) {

	/* Remove destination from seeking list since a route has been
	   found. */
	if (seek_list_remove(rrep_dest))
	    packet_buff_send(rrep_dest);

	/* If the RREP_ACK flag is set we must send a RREP
	   acknowledgement to the destination that replied... */
	if (rrep->a) {
	    RREP_ack *rrep_ack;

	    rrep_ack = rrep_ack_create();
	    aodv_socket_send((AODV_msg *) rrep_ack, fwd_rt->next_hop,
			     NEXT_HOP_WAIT, MAXTTL, 
			     &DEV_IFINDEX(fwd_rt->ifindex));
	    /* Remove RREP_ACK flag... */
	    rrep->a = 0;
	}

    } else {
	/* --- Here we FORWARD the RREP on the REVERSE route --- */
	/* If the current node is not the source node as indicated by the
	   Source IP Address in the RREP message AND a forward route has
	   been created or updated as described before, the node consults
	   its route table entry for the source node to determine the next
	   hop for the RREP packet, and then forwards the RREP towards the
	   source with its Hop Count incremented by one. */
	if ((rev_rt = rt_table_find_active(rrep_orig)) != NULL) {

	    /* Here we should do a check if we should request a RREP_ACK,
	       i.e we suspect a unidirectional link.. But how? */
	    if (0) {
		rt_table_t *neighbor;

		/* If the source of the RREP is not a neighbor we must find the
		   neighbor (link) entry which is the next hop towards the RREP
		   source... */
		if (rev_rt->dest_addr != rev_rt->next_hop)
		    neighbor = rt_table_find(rev_rt->next_hop);
		else
		    neighbor = rev_rt;

		if (neighbor != NULL && !neighbor->ack_timer.used) {
		    /* If the node we received a RREQ for is a neighbor we are
		       probably facing a unidirectional link... Better request a
		       RREP-ack */
		    rrep->a = 1;
		    neighbor->flags |= UNIDIR;

		    timer_add_msec(&neighbor->ack_timer, NEXT_HOP_WAIT);
		}
	    }
	    rrep = (RREP *) aodv_socket_queue_msg((AODV_msg *) rrep, rreplen);
	    aodv_socket_send((AODV_msg *) rrep, rev_rt->next_hop,
			     RREP_SIZE, --ip_ttl, &DEV_IFINDEX(rev_rt->ifindex));

	    /* The neighboring nodes to which a RREP was forwarded should be 
	       added as a precursor node. */
	    if (fwd_rt != NULL)
		precursor_add(fwd_rt, rev_rt->next_hop);

	    /* At each node the (reverse) route used to forward the RREP
	       has its lifetime changed to current time plus
	       ACTIVE_ROUTE_TIMEOUT. */
	    rt_table_update_timeout(rev_rt, ACTIVE_ROUTE_TIMEOUT);
	}
    }

}
static void packet_input(int fd)
#endif
{
    rt_table_t *fwd_rt, *rev_rt, *repair_rt, *next_hop_rt;
    u_int32_t dest_addr, src_addr;
    u_int8_t rreq_flags = 0;
    unsigned int ifindex;
    struct ip_data *ipd = NULL;

#ifdef NS_PORT
    ifindex = NS_IFINDEX;	// Always use ns interface
    fwd_rt = NULL;		// In case of broadcast we provide no next hop
    ipd = NULL;			// No ICMP messaging

    struct hdr_cmn *ch = HDR_CMN(p);
    struct hdr_ip *ih = HDR_IP(p);

    src_addr = ih->saddr();
    dest_addr = ih->daddr();

    /*
       Any packets with our IP address as destination arriving here are
       packets that weren't caught by any agent attached to the node.
       Throw away those.
     */
    if (dest_addr == DEV_IFINDEX(ifindex).ipaddr) {
        DEBUG(LOG_WARNING, 0,
              "processPacket: Received orphan packet. Throwing it away.");
        Packet::free(p);
        return;
    }

    /* If this is a TCP packet and we don't have a route, we should
       set the gratuituos flag in the RREQ. */
    if (ch->ptype() == PT_TCP) {
        rreq_flags |= RREQ_GRATUITOUS;
    }
#else
    int status;
    char buf[BUFSIZE], *dev_name;
    ipq_packet_msg_t *pkt;
    struct iphdr *ip;
    struct udphdr *udp;
    struct icmphdr *icmp = NULL;

    ipq_read(h, buf, BUFSIZE, 0);

    status = ipq_message_type(buf);

    if (status == NLMSG_ERROR) {
        fprintf(stderr,
                "ERROR packet_input: Check that the ip_queue.o module is loaded.\n");
        die(h);
    }

    pkt = ipq_get_packet(buf);

#ifdef DEBUG_PACKET
    DEBUG(LOG_DEBUG, 0, "Protocol %u indev=%s outdev=%s\n",
          pkt->hw_protocol, pkt->indev_name, pkt->outdev_name);
#endif

    if (pkt->hook == 0)
        dev_name = pkt->indev_name;
    else if (pkt->hook == 3)
        dev_name = pkt->outdev_name;
    else
        dev_name = NULL;

    /* We know from kaodv.c that this is an IP packet */
    ip = (struct iphdr *) pkt->payload;

    dest_addr = ntohl(ip->daddr);
    src_addr = ntohl(ip->saddr);

    switch (ip->protocol) {
    /* Don't process AODV control packets (UDP on port 654). They
       are accounted for on the aodv socket */
    case IPPROTO_UDP:
        udp = (struct udphdr *) ((char *) ip + (ip->ihl << 2));
        if (ntohs(udp->dest) == AODV_PORT || ntohs(udp->source) == AODV_PORT)
            goto accept;
        break;
    /* If this is a TCP packet and we don't have a route, we should
       set the gratuituos flag in the RREQ. */
    case IPPROTO_TCP:
        rreq_flags |= RREQ_GRATUITOUS;
        break;
    /* We set the gratuitous flag also on ICMP ECHO requests, since
       the destination will also need a route back for the reply... */
    case IPPROTO_ICMP:
        icmp = (struct icmphdr *) ((char *) ip + (ip->ihl << 2));
        if (icmp->type == ICMP_ECHO)
            rreq_flags |= RREQ_GRATUITOUS;
#ifdef DEBUG_PACKET
        DEBUG(LOG_INFO, 0, "packet_input: setting G flag for RREQ to %s",
              ip_to_str(dest_addr));
#endif

        break;
    default:
    }

#ifdef DEBUG_PACKET
    DEBUG(LOG_INFO, 0, "packet_input: pkt to %s", ip_to_str(dest_addr));
#endif

    if (dev_name)
        ifindex = if_nametoindex(dev_name);
    else
        ifindex = 0;
#endif				/* NS_PORT */

    /* If the packet is not interesting we just let it go through... */
    if ((dest_addr == AODV_BROADCAST) ||
            (dest_addr == DEV_IFINDEX(ifindex).ipaddr) ||
            (dest_addr == DEV_IFINDEX(ifindex).broadcast) ||
            ((internet_gw_mode && this_host.gateway_mode)
             && ((dest_addr & DEV_IFINDEX(ifindex).netmask) !=
                 DEV_IFINDEX(ifindex).broadcast)))
        goto accept;

    /* Find the entry of the neighboring node and the destination  (if any). */
    rev_rt = rt_table_find_active(src_addr);
    fwd_rt = rt_table_find_active(dest_addr);


    /* If a packet is received on the NF_IP_PRE_ROUTING hook,
       i.e. inbound on the interface and we don't have a route to the
       destination, we should send an RERR to the source and then drop
       the package... */
    /* NF_IP_PRE_ROUTING = 0 */

#ifdef NS_PORT
#define PACKET_IS_INBOUND ch->direction() == hdr_cmn::UP
#else
#define PACKET_IS_INBOUND pkt->hook == 0
#endif

    if ((dest_addr != DEV_IFINDEX(ifindex).ipaddr) &&
            (!fwd_rt && PACKET_IS_INBOUND)) {
        rt_table_t *rt_entry;
        u_int32_t rerr_dest;
        RERR *rerr;

        DEBUG(LOG_DEBUG, 0, "packet_input: Sending RERR for unknown dest %s",
              ip_to_str(dest_addr));

        /* There is an expired entry in the routing table we want to send
           along the seqno in the RERR... */
        rt_entry = rt_table_find(dest_addr);

        if (rt_entry) {
            rerr = rerr_create(0, rt_entry->dest_addr, rt_entry->dest_seqno);
            rt_table_update_timeout(rt_entry, DELETE_PERIOD);
        } else
            rerr = rerr_create(0, dest_addr, 0);

        /* Unicast the RERR to the source of the data transmission if
         * possible, otherwise we broadcast it. */
        if (rev_rt)
            rerr_dest = rev_rt->next_hop;
        else
            rerr_dest = AODV_BROADCAST;

        aodv_socket_send((AODV_msg *) rerr, rerr_dest,
                         RERR_CALC_SIZE(rerr), 1, &DEV_IFINDEX(ifindex));

        if (wait_on_reboot) {
            DEBUG(LOG_DEBUG, 0, "packet_input: Wait on reboot timer reset.");
            timer_add_msec(&worb_timer, DELETE_PERIOD);
        }
#ifdef NS_PORT
        drop(p, DROP_RTR_NO_ROUTE);
#else
        status = ipq_set_verdict(h, pkt->packet_id, NF_DROP, 0, NULL);
        if (status < 0)
            die(h);
#endif
        return;
    }
    /* Check if the route is currently in repair. In that case just
       buffer the packet */
    repair_rt = rt_table_find(dest_addr);

    if (repair_rt && (repair_rt->flags & LREPAIR)) {
#ifdef NS_PORT
        packet_queue_add(p, dest_addr);
#else
        packet_queue_add(pkt->packet_id, dest_addr);
#endif
        return;
    }
    /*  update_timers:  */
    /* When forwarding a packet, we update the lifetime of the
       destination's routing table entry, as well as the entry for the
       next hop neighbor (if not the same). AODV draft 10, section
       6.2. */
    if (fwd_rt && dest_addr != DEV_IFINDEX(ifindex).ipaddr) {
        rt_table_update_timeout(fwd_rt, ACTIVE_ROUTE_TIMEOUT);

        next_hop_rt = rt_table_find_active(fwd_rt->next_hop);

        if (next_hop_rt && next_hop_rt->dest_addr != fwd_rt->dest_addr)
            rt_table_update_timeout(next_hop_rt, ACTIVE_ROUTE_TIMEOUT);

    }
    /* Also update the reverse route and reverse next hop along the
       path back, since routes between originators and the destination
       are expected to be symmetric. */
    if (rev_rt) {
        rt_table_update_timeout(rev_rt, ACTIVE_ROUTE_TIMEOUT);

        next_hop_rt = rt_table_find_active(rev_rt->next_hop);

        if (next_hop_rt && next_hop_rt->dest_addr != fwd_rt->dest_addr)
            rt_table_update_timeout(next_hop_rt, ACTIVE_ROUTE_TIMEOUT);
    }
#ifdef DEBUG_PACKET
    DEBUG(LOG_INFO, 0, "packet_input: d=%s s=%s",
          ip_to_str(dest_addr), ip_to_str(src_addr));
#endif				/* DEBUG_PACKET */

    if (!fwd_rt || (fwd_rt->hcnt == 1 && (fwd_rt->flags & UNIDIR))) {
        /* Buffer packets... Packets are queued by the ip_queue_aodv.o module
           already. We only need to save the handle id, and return the proper
           verdict when we know what to do... */
#ifdef NS_PORT
        packet_queue_add(p, dest_addr);
#else
        packet_queue_add(pkt->packet_id, dest_addr);

        /* If the request is generated locally by an application, we save
           the IP header + 64 bits of data for sending an ICMP Destination
           Host Unreachable in case we don't find a route... */
        if (src_addr == DEV_IFINDEX(ifindex).ipaddr) {
            ipd = (struct ip_data *) malloc(sizeof(struct ip_data));
            if (ipd < 0) {
                perror("Malloc for IP data failed!");
                exit(-1);
            }
            ipd->len = (ip->ihl << 2) + 8;	/* IP header + 64 bits data (8 bytes) */
            memcpy(ipd->data, ip, ipd->len);
        } else
            ipd = NULL;
#endif
        rreq_route_discovery(dest_addr, rreq_flags, ipd);
        return;
    }

accept:

#ifdef NS_PORT
    if (fwd_rt)
        sendPacket(p, fwd_rt->next_hop, 0.0);
    else
        drop(p, DROP_RTR_NO_ROUTE);
#else
    status = ipq_set_verdict(h, pkt->packet_id, NF_ACCEPT, 0, NULL);
    if (status < 0)
        die(h);
#endif
    return;
}
Exemple #10
0
void NS_CLASS rrep_process(RREP * rrep, int rreplen, struct in_addr ip_src,
			   struct in_addr ip_dst, int ip_ttl,
			   unsigned int ifindex)
{
	u_int32_t rrep_lifetime, rrep_seqno, rrep_new_hcnt;
	u_int8_t pre_repair_hcnt = 0, pre_repair_flags = 0;
	rt_table_t *fwd_rt, *rev_rt;
	AODV_ext *ext;
	unsigned int extlen = 0;
	int rt_flags = 0;
	struct in_addr rrep_dest, rrep_orig;
#ifdef CONFIG_GATEWAY
	struct in_addr inet_dest_addr;
	int inet_rrep = 0;
#endif

	/* Convert to correct byte order on affeected fields: */
	rrep_dest.s_addr = rrep->dest_addr;
	rrep_orig.s_addr = rrep->orig_addr;
	rrep_seqno = ntohl(rrep->dest_seqno);
	rrep_lifetime = ntohl(rrep->lifetime);
	/* Increment RREP hop count to account for intermediate node... */
	rrep_new_hcnt = rrep->hcnt + 1;

	if (rreplen < (int)RREP_SIZE) {
		alog(LOG_WARNING, 0, __FUNCTION__,
		     "IP data field too short (%u bytes)"
		     " from %s to %s", rreplen, ip_to_str(ip_src),
		     ip_to_str(ip_dst));
		return;
	}

	/* Ignore messages which aim to a create a route to one self */
	if (rrep_dest.s_addr == DEV_IFINDEX(ifindex).ipaddr.s_addr)
		return;

	DEBUG(LOG_DEBUG, 0, "from %s about %s->%s",
	      ip_to_str(ip_src), ip_to_str(rrep_orig), ip_to_str(rrep_dest));
#ifdef DEBUG_OUTPUT
	log_pkt_fields((AODV_msg *) rrep);
#endif

	/* Determine whether there are any extensions */
	ext = (AODV_ext *) ((char *)rrep + RREP_SIZE);

	while ((rreplen - extlen) > RREP_SIZE) {
		switch (ext->type) {
		case RREP_EXT:
			DEBUG(LOG_INFO, 0, "RREP include EXTENSION");
			/* Do something here */
			break;
#ifdef CONFIG_GATEWAY
		case RREP_INET_DEST_EXT:
			if (ext->length == sizeof(u_int32_t)) {

				/* Destination address in RREP is the gateway address, while the
				 * extension holds the real destination */
				memcpy(&inet_dest_addr, AODV_EXT_DATA(ext),
				       ext->length);

				DEBUG(LOG_DEBUG, 0, "RREP_INET_DEST_EXT: <%s>",
				      ip_to_str(inet_dest_addr));
				/* This was a RREP from a gateway */
				rt_flags |= RT_GATEWAY;
				inet_rrep = 1;
				break;
			}
#endif
		default:
			alog(LOG_WARNING, 0, __FUNCTION__,
			     "Unknown or bad extension %d", ext->type);
			break;
		}
		extlen += AODV_EXT_SIZE(ext);
		ext = AODV_EXT_NEXT(ext);
	}

	/* ---------- CHECK IF WE SHOULD MAKE A FORWARD ROUTE ------------ */

	fwd_rt = rt_table_find(rrep_dest);
	rev_rt = rt_table_find(rrep_orig);

	if (!fwd_rt) {
		/* We didn't have an existing entry, so we insert a new one. */
		fwd_rt =
		    rt_table_insert(rrep_dest, ip_src, rrep_new_hcnt,
				    rrep_seqno, rrep_lifetime, VALID, rt_flags,
				    ifindex);
	} else if (fwd_rt->dest_seqno == 0
		   || (int32_t) rrep_seqno > (int32_t) fwd_rt->dest_seqno
		   || (rrep_seqno == fwd_rt->dest_seqno
		       && (fwd_rt->state == INVALID || fwd_rt->flags & RT_UNIDIR
			   || rrep_new_hcnt < fwd_rt->hcnt))) {
		pre_repair_hcnt = fwd_rt->hcnt;
		pre_repair_flags = fwd_rt->flags;

		fwd_rt =
		    rt_table_update(fwd_rt, ip_src, rrep_new_hcnt, rrep_seqno,
				    rrep_lifetime, VALID,
				    rt_flags | fwd_rt->flags);
	} else {
		if (fwd_rt->hcnt > 1) {
			DEBUG(LOG_DEBUG, 0,
			      "Dropping RREP, fwd_rt->hcnt=%d fwd_rt->seqno=%ld",
			      fwd_rt->hcnt, fwd_rt->dest_seqno);
		}
		return;
	}

	/* If the RREP_ACK flag is set we must send a RREP
	   acknowledgement to the destination that replied... */
	if (rrep->a) {
		RREP_ack *rrep_ack;

		rrep_ack = rrep_ack_create();
		aodv_socket_send((AODV_msg *) rrep_ack, fwd_rt->next_hop,
				 NEXT_HOP_WAIT, MAXTTL,
				 &DEV_IFINDEX(fwd_rt->ifindex));
		/* Remove RREP_ACK flag... */
		rrep->a = 0;
	}

	/* Check if this RREP was for us (i.e. we previously made a RREQ
	   for this host). */
	if (rrep_orig.s_addr == DEV_IFINDEX(ifindex).ipaddr.s_addr) {
#ifdef CONFIG_GATEWAY
		if (inet_rrep) {
			rt_table_t *inet_rt;
			inet_rt = rt_table_find(inet_dest_addr);

			/* Add a "fake" route indicating that this is an Internet
			 * destination, thus should be encapsulated and routed through a
			 * gateway... */
			if (!inet_rt)
				rt_table_insert(inet_dest_addr, rrep_dest,
						rrep_new_hcnt, 0, rrep_lifetime,
						VALID, RT_INET_DEST, ifindex);
			else if (inet_rt->state == INVALID
				 || rrep_new_hcnt < inet_rt->hcnt) {
				rt_table_update(inet_rt, rrep_dest,
						rrep_new_hcnt, 0, rrep_lifetime,
						VALID,
						RT_INET_DEST | inet_rt->flags);
			} else {
				DEBUG(LOG_DEBUG, 0,
				      "INET Response, but no update %s",
				      ip_to_str(inet_dest_addr));
			}
		}
#endif				/* CONFIG_GATEWAY */

		/* If the route was previously in repair, a NO DELETE RERR should be
		   sent to the source of the route, so that it may choose to reinitiate
		   route discovery for the destination. Fixed a bug here that caused the
		   repair flag to be unset and the RERR never being sent. Thanks to
		   McWood <*****@*****.**> for discovering this. */
		if (pre_repair_flags & RT_REPAIR) {
			if (fwd_rt->hcnt > pre_repair_hcnt) {
				RERR *rerr;
				u_int8_t rerr_flags = 0;
				struct in_addr dest;

				dest.s_addr = AODV_BROADCAST;

				rerr_flags |= RERR_NODELETE;
				rerr =
				    rerr_create(rerr_flags, fwd_rt->dest_addr,
						fwd_rt->dest_seqno);

				if (fwd_rt->nprec)
					aodv_socket_send((AODV_msg *) rerr,
							 dest,
							 RERR_CALC_SIZE(rerr),
							 1,
							 &DEV_IFINDEX(fwd_rt->
								      ifindex));
			}
		}
	} else {
		/* --- Here we FORWARD the RREP on the REVERSE route --- */
		if (rev_rt && rev_rt->state == VALID) {
			rrep_forward(rrep, rreplen, rev_rt, fwd_rt, --ip_ttl);
		} else {
			DEBUG(LOG_DEBUG, 0,
			      "Could not forward RREP - NO ROUTE!!!");
		}
	}

	if (!llfeedback && optimized_hellos)
		hello_start();
}
Exemple #11
0
static void nl_callback(int sock)
{
	int len, attrlen;
	socklen_t addrlen;
	struct nlmsghdr *nlm;
	struct nlmsgerr *nlmerr;
	char buf[BUFLEN];
	struct in_addr dest_addr, src_addr;	
	struct ifaddrmsg *ifm;
	struct rtattr *rta;
	kaodv_rt_msg_t *m;
	rt_table_t *rt, *fwd_rt, *rev_rt = NULL;
		
	addrlen = sizeof(peer);


	len = recvfrom(sock, buf, BUFLEN, 0, (struct sockaddr *)&peer, &addrlen);

	if (len <= 0)
		return;
	
	nlm = (struct nlmsghdr *)buf;

	switch (nlm->nlmsg_type) {
	case NLMSG_ERROR:
		nlmerr = NLMSG_DATA(nlm);
		if (nlmerr->error == 0) {
			DEBUG(LOG_DEBUG, 0, "NLMSG_ACK");
		} else
			DEBUG(LOG_DEBUG, 0, "NLMSG_ERROR, error=%d", 
			      nlmerr->error);
		break;
	case RTM_NEWLINK:
		DEBUG(LOG_DEBUG, 0, "RTM_NEWADDR");
		break;
	case RTM_NEWADDR:
		DEBUG(LOG_DEBUG, 0, "RTM_NEWADDR");

		ifm = NLMSG_DATA(nlm);

		rta = (struct rtattr *)((char *)ifm + sizeof(ifm));
		
		attrlen = nlm->nlmsg_len - 
			sizeof(struct nlmsghdr) - 
			sizeof(struct ifaddrmsg);
		
		for (; RTA_OK(rta, attrlen); rta = RTA_NEXT(rta, attrlen)) {

			if (rta->rta_type == IFA_ADDRESS) {
				struct in_addr ifaddr;
				
				memcpy(&ifaddr, RTA_DATA(rta), RTA_PAYLOAD(rta));
				
				DEBUG(LOG_DEBUG, 0, 
				      "Interface index %d changed address to %s", 
				      ifm->ifa_index, ip_to_str(ifaddr));
				
			}
		}
		break;
	case KAODVM_TIMEOUT:
		m = NLMSG_DATA(nlm);
		dest_addr.s_addr = m->dst;

		DEBUG(LOG_DEBUG, 0,
		      "Got TIMEOUT msg from kernel for %s",
		      ip_to_str(dest_addr));

		rt = rt_table_find(dest_addr);

		if (rt && rt->state == VALID)
			route_expire_timeout(rt);
		else
			DEBUG(LOG_DEBUG, 0,
			      "Got rt timeoute event but there is no route");
		break;
	case KAODVM_NOROUTE:
		m = NLMSG_DATA(nlm);
		dest_addr.s_addr = m->dst;

		DEBUG(LOG_DEBUG, 0,
		      "Got NOROUTE msg from kernel for %s",
		      ip_to_str(dest_addr));

		rreq_route_discovery(dest_addr, 0, NULL);
		break;
	case KAODVM_REPAIR:
		m = NLMSG_DATA(nlm);
		dest_addr.s_addr = m->dst;
		src_addr.s_addr = m->src;

		DEBUG(LOG_DEBUG, 0, "Got REPAIR msg from kernel for %s",
		      ip_to_str(dest_addr));

		fwd_rt = rt_table_find(dest_addr);

		if (fwd_rt)
			rreq_local_repair(fwd_rt, src_addr, NULL);

		break;
	case KAODVM_ROUTE_UPDATE:
		m = NLMSG_DATA(nlm);
		dest_addr.s_addr = m->dst;
		src_addr.s_addr = m->src;
	
		if (dest_addr.s_addr == AODV_BROADCAST ||
		    dest_addr.s_addr ==
		    DEV_IFINDEX(m->ifindex).broadcast.s_addr)
			return;

		fwd_rt = rt_table_find(dest_addr);
		rev_rt = rt_table_find(src_addr);

		rt_table_update_route_timeouts(fwd_rt, rev_rt);

		break;
	case KAODVM_SEND_RERR:
		m = NLMSG_DATA(nlm);
		dest_addr.s_addr = m->dst;
		src_addr.s_addr = m->src;

		if (dest_addr.s_addr == AODV_BROADCAST ||
		    dest_addr.s_addr ==
		    DEV_IFINDEX(m->ifindex).broadcast.s_addr)
			return;

		fwd_rt = rt_table_find(dest_addr);
		rev_rt = rt_table_find(src_addr);

		do {
			struct in_addr rerr_dest;
			RERR *rerr;

			DEBUG(LOG_DEBUG, 0,
			      "Sending RERR for unsolicited message from %s to dest %s",
			      ip_to_str(src_addr),
			      ip_to_str(dest_addr));

			if (fwd_rt) {
				rerr = rerr_create(0, fwd_rt->dest_addr,
						   fwd_rt->dest_seqno);

				rt_table_update_timeout(fwd_rt,
							DELETE_PERIOD);
			} else
				rerr = rerr_create(0, dest_addr, 0);

			/* Unicast the RERR to the source of the data transmission
			 * if possible, otherwise we broadcast it. */

			if (rev_rt && rev_rt->state == VALID)
				rerr_dest = rev_rt->next_hop;
			else
				rerr_dest.s_addr = AODV_BROADCAST;

			aodv_socket_send((AODV_msg *) rerr, rerr_dest,
					 RERR_CALC_SIZE(rerr), 1,
					 &DEV_IFINDEX(m->ifindex));

			if (wait_on_reboot) {
				DEBUG(LOG_DEBUG, 0,
				      "Wait on reboot timer reset.");
				timer_set_timeout(&worb_timer,
						  DELETE_PERIOD);
			}
		} while (0);
		break;
	default:
		DEBUG(LOG_DEBUG, 0, "Got mesg type=%d\n", nlm->nlmsg_type);
	}
}