Example #1
0
File: route.c Project: F0rth/pimd
mrtentry_t *switch_shortest_path(u_int32 source, u_int32 group)
{
    mrtentry_t *mrtentry_ptr;

    /* TODO: XXX: prepare and send immediately the (S,G) join? */
    if ((mrtentry_ptr = find_route(source, group, MRTF_SG, CREATE)) !=
        (mrtentry_t *)NULL) {
        if (mrtentry_ptr->flags & MRTF_NEW) {
            mrtentry_ptr->flags &= ~MRTF_NEW;
        }
        else if (mrtentry_ptr->flags & MRTF_RP) {
            /* (S,G)RPbit with iif toward RP. Reset to (S,G) with iif
             * toward S. Delete the kernel cache (if any), because
             * change_interfaces() will reset it with iif toward S
             * and no data will arrive from RP before the switch
             * really occurs.
             */
            mrtentry_ptr->flags &= ~MRTF_RP;
            mrtentry_ptr->incoming = mrtentry_ptr->source->incoming;
            mrtentry_ptr->upstream = mrtentry_ptr->source->upstream;
            delete_mrtentry_all_kernel_cache(mrtentry_ptr);
            change_interfaces(mrtentry_ptr,
                              mrtentry_ptr->incoming,
                              mrtentry_ptr->joined_oifs,
                              mrtentry_ptr->pruned_oifs,
                              mrtentry_ptr->leaves,
                              mrtentry_ptr->asserted_oifs, 0);
        }

        SET_TIMER(mrtentry_ptr->timer, PIM_DATA_TIMEOUT);
        FIRE_TIMER(mrtentry_ptr->jp_timer);
    }

    return mrtentry_ptr;
}
Example #2
0
status_t
remove_route(struct net_domain* _domain, const struct net_route* removeRoute)
{
	struct net_domain_private* domain = (net_domain_private*)_domain;

	TRACE("remove route from domain %s: dest %s, mask %s, gw %s, flags %lx\n",
		domain->name,
		AddressString(domain, removeRoute->destination
			? removeRoute->destination : NULL).Data(),
		AddressString(domain, removeRoute->mask
			? removeRoute->mask : NULL).Data(),
		AddressString(domain, removeRoute->gateway
			? removeRoute->gateway : NULL).Data(),
		removeRoute->flags);

	RecursiveLocker locker(domain->lock);

	net_route_private* route = find_route(domain, removeRoute);
	if (route == NULL)
		return B_ENTRY_NOT_FOUND;

	domain->routes.Remove(route);

	put_route_internal(domain, route);
	update_route_infos(domain);

	return B_OK;
}
Example #3
0
status_t
get_route_information(struct net_domain* _domain, void* value, size_t length)
{
	struct net_domain_private* domain = (net_domain_private*)_domain;

	if (length < sizeof(route_entry))
		return B_BAD_VALUE;

	route_entry entry;
	if (user_memcpy(&entry, value, sizeof(route_entry)) < B_OK)
		return B_BAD_ADDRESS;

	sockaddr_storage destination;
	status_t status = user_copy_address(entry.destination, &destination);
	if (status != B_OK)
		return status;

	RecursiveLocker locker(domain->lock);

	net_route_private* route = find_route(domain, (sockaddr*)&destination);
	if (route == NULL)
		return B_ENTRY_NOT_FOUND;

	status = fill_route_entry(&entry, value, length, route);
	if (status != B_OK)
		return status;

	return user_memcpy(value, &entry, sizeof(route_entry));
}
Example #4
0
static struct net_route*
get_route_internal(struct net_domain_private* domain,
	const struct sockaddr* address)
{
	ASSERT_LOCKED_RECURSIVE(&domain->lock);
	net_route_private* route = NULL;

	if (address->sa_family == AF_LINK) {
		// special address to find an interface directly
		RouteList::Iterator iterator = domain->routes.GetIterator();
		const sockaddr_dl* link = (const sockaddr_dl*)address;

		while (iterator.HasNext()) {
			route = iterator.Next();

			net_device* device = route->interface_address->interface->device;

			if ((link->sdl_nlen > 0
					&& !strncmp(device->name, (const char*)link->sdl_data,
							IF_NAMESIZE))
				|| (link->sdl_nlen == 0 && link->sdl_alen > 0
					&& !memcmp(LLADDR(link), device->address.data,
							device->address.length)))
				break;
		}
	} else
		route = find_route(domain, address);

	if (route != NULL && atomic_add(&route->ref_count, 1) == 0) {
		// route has been deleted already
		route = NULL;
	}

	return route;
}
Example #5
0
static int __send(struct vport *vport, struct sk_buff *skb,
		  int tunnel_hlen,
		  __be32 seq, __be16 gre64_flag)
{
	struct ovs_key_ipv4_tunnel *tun_key = &OVS_CB(skb)->tun_info->tunnel;
	struct rtable *rt;
	int min_headroom;
	__be16 df;
	__be32 saddr;
	int err;

	/* Route lookup */
	saddr = tun_key->ipv4_src;
	rt = find_route(ovs_dp_get_net(vport->dp),
			&saddr, tun_key->ipv4_dst,
			IPPROTO_GRE, tun_key->ipv4_tos,
			skb->mark);
	if (IS_ERR(rt)) {
		err = PTR_ERR(rt);
		goto error;
	}

	min_headroom = LL_RESERVED_SPACE(rt_dst(rt).dev) + rt_dst(rt).header_len
			+ tunnel_hlen + sizeof(struct iphdr)
			+ (vlan_tx_tag_present(skb) ? VLAN_HLEN : 0);

	if (skb_headroom(skb) < min_headroom || skb_header_cloned(skb)) {
		int head_delta = SKB_DATA_ALIGN(min_headroom -
						skb_headroom(skb) +
						16);
		err = pskb_expand_head(skb, max_t(int, head_delta, 0),
					0, GFP_ATOMIC);
		if (unlikely(err))
			goto err_free_rt;
	}
Example #6
0
void route (WiFiClient socket, Router *router, uint8_t *req) {
#else
void route (uint8_t socket, Router *router, uint8_t *req) {
#endif
  Request *request;
  Response *response;

  request = parse_request(req);
  response = response_create(socket);

  if (router->write) {
    response->write = router->write;
  }

  if (request->method == HTTP_ERROR) {
    five_hundred(request, response);
  } else {
    int8_t found = find_route(router, request->path);

    if (found != -1) {
      router->routes[found].method(request, response);
    } else {
      four_oh_four(request, response);
    }
  }
}
Example #7
0
/* IMPORTANT CALLS */
int
get_dsteth(ipaddr_t dstaddr,ethaddr_t ethaddr,int *ifnum) {
  /* first search interfaces */
  ipaddr_t gateway;

  switch(find_if(dstaddr,ifnum)) {
  case IFRET_LOOPBACK:
    //printf("Directly on interface (loopback)\n");
    bzero(ethaddr,6); 
    return 0;
  case IFRET_RESOLVE:
    //printf("Directly on interface\n");
    return arp_resolve_ip(dstaddr,ethaddr,*ifnum);
  case IFRET_BROADCAST:
    //printf("Broadcast\n");
    memset(ethaddr,0xff,6);
    return 0;
  case IFRET_NOTFOUND:
    /* fall through */
  }
  if (find_route(dstaddr,gateway) == 0) {
    //printf("Via gateway: %s\n",pripaddr(gateway));
    switch(find_if(gateway,ifnum)) {
    case IFRET_LOOPBACK:
      bzero(ethaddr,6); 
      return 0;
    case IFRET_RESOLVE:
      //printf("Directly on interface\n");
      return arp_resolve_ip(gateway,ethaddr,*ifnum);
    case IFRET_BROADCAST:
      //printf("Broadcast\n");
      memset(ethaddr,0xff,6);
      return 0;
    case IFRET_NOTFOUND:
      /* fall through */
    }
  }
    
  printf("get_dsteth: could not find route to destination: %s\n",pripaddr(dstaddr));
  return -1;
}

#define ASSERTIFNUM(ifnum)				\
  EnterCritical(); 					\
  assert(ifnum < GETNUMIFENTRIES && ifnum >= 0);	\
  ExitCritical();

void
get_ifnum_ethernet(int ifnum, ethaddr_t ethaddr) {
  if_entry_p ife;
  ASSERTIFNUM(ifnum);
  EnterCritical();
  ife = GETIFP(ifnum);
  bcopy(ife->ethaddr,ethaddr, 6);
  ExitCritical();
}
Example #8
0
static int vxlan_tnl_send(struct vport *vport, struct sk_buff *skb)
{
	struct ovs_key_ipv4_tunnel *tun_key;
	struct net *net = ovs_dp_get_net(vport->dp);
	struct vxlan_port *vxlan_port = vxlan_vport(vport);
	__be16 dst_port = inet_sport(vxlan_port->vs->sock->sk);
	struct vxlan_metadata md = {0};
	struct rtable *rt;
	__be16 src_port;
	__be32 saddr;
	__be16 df;
	int err;
	u32 vxflags;

	if (unlikely(!OVS_CB(skb)->egress_tun_info)) {
		err = -EINVAL;
		goto error;
	}

	tun_key = &OVS_CB(skb)->egress_tun_info->tunnel;

	/* Route lookup */
	saddr = tun_key->ipv4_src;
	rt = find_route(ovs_dp_get_net(vport->dp),
			&saddr, tun_key->ipv4_dst,
			IPPROTO_UDP, tun_key->ipv4_tos,
			skb->mark);
	if (IS_ERR(rt)) {
		err = PTR_ERR(rt);
		goto error;
	}

	df = tun_key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0;
	skb->ignore_df = 1;

	src_port = udp_flow_src_port(net, skb, 0, 0, true);
	md.vni = htonl(be64_to_cpu(tun_key->tun_id) << 8);
	md.gbp = vxlan_ext_gbp(skb);
	vxflags = vxlan_port->exts |
		      (tun_key->tun_flags & TUNNEL_CSUM ? VXLAN_F_UDP_CSUM : 0);

	err = vxlan_xmit_skb(vxlan_port->vs, rt, skb,
			     saddr, tun_key->ipv4_dst,
			     tun_key->ipv4_tos,
			     tun_key->ipv4_ttl, df,
			     src_port, dst_port,
			     &md, false, vxflags);
	if (err < 0)
		ip_rt_put(rt);
	return err;
error:
	kfree_skb(skb);
	return err;
}
Example #9
0
File: route.c Project: F0rth/pimd
/*
 * TODO: XXX: currently `source` is not used. To be used with IGMPv3 where
 * we have source-specific joins/prunes.
 */
void delete_leaf(vifi_t vifi, u_int32 source __attribute__((unused)), u_int32 group)
{
    mrtentry_t *mrtentry_ptr;
    mrtentry_t *mrtentry_srcs;
    vifbitmap_t new_oifs;
    vifbitmap_t old_oifs;
    vifbitmap_t new_leaves;

    mrtentry_ptr = find_route(INADDR_ANY_N, group, MRTF_WC, DONT_CREATE);
    if (mrtentry_ptr == (mrtentry_t *)NULL)
        return;

    if (!VIFM_ISSET(vifi, mrtentry_ptr->leaves))
        return;      /* This interface wasn't leaf */

    calc_oifs(mrtentry_ptr, &old_oifs);
    VIFM_COPY(mrtentry_ptr->leaves, new_leaves);
    VIFM_CLR(vifi, new_leaves);
    change_interfaces(mrtentry_ptr,
                      mrtentry_ptr->incoming,
                      mrtentry_ptr->joined_oifs,
                      mrtentry_ptr->pruned_oifs,
                      new_leaves,
                      mrtentry_ptr->asserted_oifs, 0);
    calc_oifs(mrtentry_ptr, &new_oifs);
    if ((!VIFM_ISEMPTY(old_oifs)) && VIFM_ISEMPTY(new_oifs)) {
        /* The result oifs have changed from non-NULL to NULL */
        FIRE_TIMER(mrtentry_ptr->jp_timer);  /* Timeout the Join/Prune timer */
        /* TODO: explicitly call the function?
           send_pim_join_prune(mrtentry_ptr->upstream->vifi,
           mrtentry_ptr->upstream, PIM_JOIN_PRUNE_HOLDTIME);
        */
    }
    /* Check all (S,G) entries and clear the inherited "leaf" flag.
     * TODO: XXX: This won't work for IGMPv3, because there we don't know
     * whether the (S,G) leaf oif was inherited from the (*,G) entry or
     * was created by source specific IGMP join.
     */
    for (mrtentry_srcs = mrtentry_ptr->group->mrtlink;
         mrtentry_srcs != (mrtentry_t *)NULL;
         mrtentry_srcs = mrtentry_srcs->grpnext) {
        VIFM_COPY(mrtentry_srcs->leaves, new_leaves);
        VIFM_CLR(vifi, new_leaves);
        change_interfaces(mrtentry_srcs,
                          mrtentry_srcs->incoming,
                          mrtentry_srcs->joined_oifs,
                          mrtentry_srcs->pruned_oifs,
                          new_leaves,
                          mrtentry_srcs->asserted_oifs, 0);
    }

}
Example #10
0
File: route.c Project: F0rth/pimd
/*
 * A multicast packet has been received on wrong iif by the kernel.
 * Check for a matching entry. If there is (S,G) with reset SPTbit and
 * the packet was received on the iif toward the source, this completes
 * the switch to the shortest path and triggers (S,G) prune toward the RP
 * (unless I am the RP).
 * Otherwise, if the packet's iif is in the oiflist of the routing entry,
 * trigger an Assert.
 */
static void process_wrong_iif(struct igmpmsg *igmpctl)
{
    u_int32 source;
    u_int32 group;
    vifi_t  iif;
    mrtentry_t *mrtentry_ptr;

    group  = igmpctl->im_dst.s_addr;
    source = igmpctl->im_src.s_addr;
    iif    = igmpctl->im_vif;

    /* Don't create routing entries for the LAN scoped addresses */
    if (ntohl(group) <= INADDR_MAX_LOCAL_GROUP)
        return;

    /* Ignore if it comes on register vif. register vif is neither SPT iif,
     * neither is used to send asserts out.
     */
    if (uvifs[iif].uv_flags & VIFF_REGISTER)
        return;

    mrtentry_ptr = find_route(source, group, MRTF_SG | MRTF_WC | MRTF_PMBR,
                              DONT_CREATE);
    if (mrtentry_ptr == NULL)
        return;

    /*
     * TODO: check again!
     */
    if (mrtentry_ptr->flags & MRTF_SG) {
        if (!(mrtentry_ptr->flags & MRTF_SPT)) {
            if (mrtentry_ptr->source->incoming == iif) {
                /* Switch to the Shortest Path */
                mrtentry_ptr->flags |= MRTF_SPT;
                mrtentry_ptr->flags &= ~MRTF_RP;
                add_kernel_cache(mrtentry_ptr, source, group, MFC_MOVE_FORCE);
                k_chg_mfc(igmp_socket, source, group, iif,
                          mrtentry_ptr->oifs, mrtentry_ptr->group->rpaddr);
                FIRE_TIMER(mrtentry_ptr->jp_timer);
#ifdef RSRR
                rsrr_cache_send(mrtentry_ptr, RSRR_NOTIFICATION_OK);
#endif /* RSRR */

                return;
            }
        }
    }

    /* Trigger an Assert */
    if (VIFM_ISSET(iif, mrtentry_ptr->oifs))
        send_pim_assert(source, group, iif, mrtentry_ptr);
}
			static Route find_route(int** map, int sx, int sy, int ex, int ey) {
				if (sx > ex || sy > ey)
					return Route();

				if (map[sx][sy] == 1) // blocked.
					return Route();	// cannot enter here.

				if ((sx == ex && sy + 1 == ex) ||
					(sx + 1 == ex && sy == ex)) {
					Route ret;
					ret.emplace_back(std::make_pair(ex, ey));
					return ret;
				}

				auto route = find_route(map, sx + 1, sy, ex, ey);
				if (route.size() > 0) {
					return route;
				} else {
					auto route2 = find_route(map, sx, sy + 1, ex, ey);
					return route;
				}
			}
Example #12
0
static int vxlan_tnl_send(struct vport *vport, struct sk_buff *skb)
{
	struct vxlan_port *vxlan_port = vxlan_vport(vport);
	__be16 dst_port = inet_sport(vxlan_port->vs->sock->sk);
	struct rtable *rt;
	__be16 src_port;
	__be32 saddr;
	__be16 df;
	int port_min;
	int port_max;
	int err;

	if (unlikely(!OVS_CB(skb)->tun_key)) {
		err = -EINVAL;
		goto error;
	}

	/* Route lookup */
	saddr = OVS_CB(skb)->tun_key->ipv4_src;
	rt = find_route(ovs_dp_get_net(vport->dp),
			&saddr,
			OVS_CB(skb)->tun_key->ipv4_dst,
			IPPROTO_UDP,
			OVS_CB(skb)->tun_key->ipv4_tos,
			skb->mark);
	if (IS_ERR(rt)) {
		err = PTR_ERR(rt);
		goto error;
	}

	df = OVS_CB(skb)->tun_key->tun_flags & TUNNEL_DONT_FRAGMENT ?
		htons(IP_DF) : 0;

	skb->local_df = 1;

	inet_get_local_port_range(&port_min, &port_max);
	src_port = vxlan_src_port(port_min, port_max, skb);

	err = vxlan_xmit_skb(vxlan_port->vs, rt, skb,
			     saddr, OVS_CB(skb)->tun_key->ipv4_dst,
			     OVS_CB(skb)->tun_key->ipv4_tos,
			     OVS_CB(skb)->tun_key->ipv4_ttl, df,
			     src_port, dst_port,
			     htonl(be64_to_cpu(OVS_CB(skb)->tun_key->tun_id) << 8));
	if (err < 0)
		ip_rt_put(rt);
error:
	return err;
}
int looking_for_access_areas(void) {
    int num_of_accessible_areas = 0;
    for (int i = 0, j = 0; j < size_of_line - 1; ++j)
        if (grid[i][j] == 0 || grid[i][j] == 2) {
            find_route(i, j);
            num_of_accessible_areas++;
        }
    for (int i = 0, j = 0; i < size_of_column - 1; ++i)
        if (grid[i][0] == 0 || grid[i][0] == 1) {
            find_route(i, j);
            num_of_accessible_areas++;
        }
    for (int i = size_of_column - 1, j = 0; j < size_of_line - 1; ++j)
        if (grid[size_of_column-1][j] == 0) {
            find_route(i, j);
            num_of_accessible_areas++;
        }
    for (int i = 0, j = size_of_line - 1; i < size_of_column - 1; ++i)
        if (grid[i][size_of_line-1] == 0) {
            find_route(i, j);
            num_of_accessible_areas++;
        }
    return num_of_accessible_areas;
}
static void router_dispatch(void *data,
			    struct stasis_subscription *sub,
			    struct stasis_message *message)
{
	struct stasis_message_router *router = data;
	struct stasis_message_route route;

	if (find_route(router, message, &route) == 0) {
		route.callback(route.data, sub, message);
	}

	if (stasis_subscription_final_message(sub, message)) {
		ao2_cleanup(router);
	}
}
Example #15
0
int ovs_tunnel_get_egress_info(struct ovs_tunnel_info *egress_tun_info,
			       struct net *net,
			       const struct ovs_tunnel_info *tun_info,
			       u8 ipproto,
			       u32 skb_mark,
			       __be16 tp_src,
			       __be16 tp_dst)
{
	const struct ovs_key_ipv4_tunnel *tun_key;
	struct rtable *rt;
	__be32 saddr;

	if (unlikely(!tun_info))
		return -EINVAL;

	tun_key = &tun_info->tunnel;
	saddr = tun_key->ipv4_src;
	/* Route lookup to get srouce IP address: saddr.
	 * The process may need to be changed if the corresponding process
	 * in vports ops changed.
	 */
	rt = find_route(net,
			&saddr,
			tun_key->ipv4_dst,
			ipproto,
			tun_key->ipv4_tos,
			skb_mark);
	if (IS_ERR(rt))
		return PTR_ERR(rt);

	ip_rt_put(rt);

	/* Generate egress_tun_info based on tun_info,
	 * saddr, tp_src and tp_dst
	 */
	__ovs_flow_tun_info_init(egress_tun_info,
				 saddr, tun_key->ipv4_dst,
				 tun_key->ipv4_tos,
				 tun_key->ipv4_ttl,
				 tp_src, tp_dst,
				 tun_key->tun_id,
				 tun_key->tun_flags,
				 tun_info->options,
				 tun_info->options_len);

	return 0;
}
Example #16
0
static int stt_tnl_send(struct vport *vport, struct sk_buff *skb)
{
	struct net *net = ovs_dp_get_net(vport->dp);
	struct stt_port *stt_port = stt_vport(vport);
	__be16 dport = inet_sk(stt_port->stt_sock->sock->sk)->inet_sport;
	const struct ovs_key_ipv4_tunnel *tun_key;
	const struct ovs_tunnel_info *tun_info;
	struct rtable *rt;
	__be16 sport;
	__be32 saddr;
	__be16 df;
	int err;

	tun_info = OVS_CB(skb)->egress_tun_info;
	if (unlikely(!tun_info)) {
		err = -EINVAL;
		goto error;
	}

	tun_key = &tun_info->tunnel;
	/* Route lookup */
	saddr = tun_key->ipv4_src;
	rt = find_route(ovs_dp_get_net(vport->dp),
			&saddr, tun_key->ipv4_dst,
			IPPROTO_TCP, tun_key->ipv4_tos,
			skb->mark);

	if (IS_ERR(rt)) {
		err = PTR_ERR(rt);
		goto error;
	}

	df = tun_key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0;
	sport = udp_flow_src_port(net, skb, 1, USHRT_MAX, true);
	skb->ignore_df = 1;

	return stt_xmit_skb(skb, rt, saddr, tun_key->ipv4_dst,
			    tun_key->ipv4_tos, tun_key->ipv4_ttl,
			    df, sport, dport, tun_key->tun_id);
error:
	kfree_skb(skb);
	return err;
}
Example #17
0
File: flexd.c Project: ve7fet/fpac
int download_dest(char *gateway, char *fname)
{
	FILE *tmp;
	static char *addr;
       	char port[14];
	char buffer[4096], path[AX25_MAX_DIGIS * 10];
	int buflen = 4096;
	char *commands[10], *dlist[9];		/* Destination + 8 digipeaters */
	fd_set read_fd;
	int paclen = 0;
	int window = 0;
	int n, cmd_send = 0, cmd_ack = 0, c, k;
	int s = 0;
	int addrlen = 0;
	int ret;
	unsigned int retlen;
	char *cp;
	struct sockaddr_rose rosebind;
	struct sockaddr_rose roseconnect;
	struct full_sockaddr_ax25 nrbind, nrconnect;

	union {
		struct full_sockaddr_ax25 ax25;
		struct sockaddr_rose  rose;
	} sockaddr;

	char digicall[10] = "\0";
	char destcall[10] = "\0";
	char destaddr[11] = "\0";
	static int af_mode = 0;

	memset(&sockaddr.rose, 0x00, sizeof(struct sockaddr_rose));
	memset(&rosebind, 0x00, sizeof(struct sockaddr_rose));
	memset(&roseconnect, 0x00, sizeof(struct sockaddr_rose));
	memset(&nrbind, 0x00, sizeof(struct full_sockaddr_ax25));
	memset(&nrconnect, 0x00, sizeof(struct sockaddr_ax25));

	gw = find_route(gateway, NULL);
	if (gw == NULL) {
		fprintf(stderr,"flexd connect: FlexGate %s not found in file: %s\n",
				gateway, FLEXD_CONF_FILE);
		return -1;
	} else {
		*path = '\0';
		for (k = 0; k < AX25_MAX_DIGIS; k++) {
			if (gw->digis[k][0] == '\0')
				dlist[k + 1] = NULL;
			else
				dlist[k + 1] = gw->digis[k];
		}
		dlist[0] = gw->dest_call;
		strcpy(port, gw->dev);
	}
	if (af_mode == 0) {

		if ((addr = ax25_config_get_addr(port)) == NULL) {
			nr_config_load_ports();

			if ((addr = nr_config_get_addr(port)) == NULL) {
				rs_config_load_ports();

				if ((addr = rs_config_get_addr(port)) == NULL) {
					fprintf(stderr,
						"flexd: invalid port setting\n");
					return -1;
				} else {
					af_mode = AF_ROSE;
				}
			} else {
				af_mode = AF_NETROM;
			}
		} else {
			af_mode = AF_AX25;
		}
	}

	switch (af_mode) {
	case AF_ROSE:
		paclen = rs_config_get_paclen(port);

		if (dlist[0] == NULL || dlist[1] == NULL) {
			fprintf(stderr,
				"flexd: too few arguments for Rose\n");
			return (-1);
		}
	/*
	 * Parse the passed values for correctness.
	 */
	roseconnect.srose_family = rosebind.srose_family = AF_ROSE;
	roseconnect.srose_ndigis = rosebind.srose_ndigis = 0;

	/*
	if (dlist[2] == NULL) {	*/
		strcpy(destaddr, dlist[1]);
		strcpy(destcall, dlist[0]);
/*		*digicall ='\0';*/
/*	}
	else {
		strcpy(destaddr, dlist[2]);
		strcpy(digicall, dlist[0]);
		strcpy(destcall, dlist[1]);
	} */

	if (ax25_aton_entry(destcall, roseconnect.srose_call.ax25_call) == -1) {
		sprintf(buffer, "ERROR: invalid destination callsign - %s\n", destcall);
		fprintf(stderr, "%s\n", buffer);
		return (-1);
	}

	if (rose_aton(destaddr, roseconnect.srose_addr.rose_addr) == -1) {
		sprintf(buffer, "ERROR: invalid destination Rose address - %s\n", destaddr);
		fprintf(stderr, "%s\n", buffer);
		return (-1);
	}
		rosebind.srose_family = AF_ROSE;
		roseconnect.srose_family = AF_ROSE;
		sockaddr.rose.srose_family = AF_ROSE;
		addrlen = sizeof(struct sockaddr_rose);
	/*
	 * Open the socket into the kernel.
	 */
	if ((s = socket(AF_ROSE, SOCK_SEQPACKET, 0)) < 0) {
		sprintf(buffer, "ERROR: cannot open Rose socket, %s\n", strerror(errno));
		fprintf(stderr, "%s\n", buffer);
		close(s);
		return (-1);
	}
	/*
	 * Set our AX.25 callsign and Rose address accordingly.
	 */
	if (rose_aton(addr, rosebind.srose_addr.rose_addr) == -1) {
		sprintf(buffer, "ERROR: invalid Rose port address - %s\n", addr);
		fprintf(stderr, "%s\n", buffer);
		close(s);
		return (-1);
	}

	if (ax25_aton_entry(mycall, rosebind.srose_call.ax25_call) == -1) {
		sprintf(buffer, "ERROR: invalid callsign - %s\n", mycall);
		fprintf(stderr, "%s\n", buffer);
		close(s);
		return (-1);
	}

	if (bind(s, (struct sockaddr *)&rosebind, addrlen) != 0) {
		sprintf(buffer, "ERROR: cannot bind Rose socket, %s\n", strerror(errno));
		fprintf(stderr, "%s\n", buffer);
		close(s);
		return (-1);
	}
	/*
	 * Lets try and connect to the far end.
	 */
	if (connect(s, (struct sockaddr *)&roseconnect, addrlen) != 0) {
		switch (errno) {
			case ECONNREFUSED:
				strcpy(buffer, "*** Flexd: Connection refused - will try again later\n");
				break;
			case ENETUNREACH:
				strcpy(buffer, "*** Flexd: Route is closed - will try again later\n");
				break;
			case EINTR:
				strcpy(buffer, "*** Flexd: Connection timed out - will try again later\n");
				break;
			default:
				sprintf(buffer, "Flexd: ERROR cannot connect to Rose address %s\n", strerror(errno));
				break;
		}
		fprintf(stderr, "%s\n", buffer);
		close(s);
		return (1);
	}
	break;
	case AF_NETROM:
		if (paclen == 0)
			paclen = nr_config_get_paclen(port);

		if (dlist[0] == NULL) {
			fprintf(stderr,
				"flexd: too few arguments for NET/ROM\n");
			return (-1);
		}
	/*
	 * Parse the passed values for correctness.
	 */
	nrconnect.fsa_ax25.sax25_family = AF_NETROM;
	nrbind.fsa_ax25.sax25_family = AF_NETROM;
	nrbind.fsa_ax25.sax25_ndigis    = 1;
	nrconnect.fsa_ax25.sax25_ndigis = 0;
	addrlen = sizeof(struct full_sockaddr_ax25);

	if (ax25_aton_entry(addr, nrbind.fsa_ax25.sax25_call.ax25_call) == -1) {
		sprintf(buffer, "ERROR: invalid NET/ROM port callsign - %s\n", addr);
		fprintf(stderr, "%s\n", buffer);
		return (-1);
	}

	if (ax25_aton_entry(mycall, nrbind.fsa_digipeater[0].ax25_call) == -1) {
		sprintf(buffer, "ERROR: invalid callsign - %s\n", mycall);
		fprintf(stderr, "%s\n", buffer);
		return (-1);
	}

/*	if (dlist[1] == NULL) { */
		strcpy(destcall, dlist[0]);
/*	}
	else {
		strcpy(destcall, dlist[1]);
		strcpy(digicall, dlist[0]);
	} */

	/*FSA*/
	fprintf(stderr, "\nCase AF_NETROM destcall: '%s' digicall: '%s' mycall: '%s' port callsign: '%s'\n", destcall, digicall, mycall, addr);
	/*FSA*/
        printf("Case AF_NETROM destcall: '%s' digicall: '%s' mycall: '%s' port callsign: '%s' addrlen %d\n",
		destcall, digicall, mycall, addr, addrlen);

	if (ax25_aton_entry(destcall, nrconnect.fsa_ax25.sax25_call.ax25_call) == -1) {
		sprintf(buffer, "ERROR: invalid destination callsign - %s\n", destcall);
		fprintf(stderr, "%s\n", buffer);
		return (-1);
		}
	/*
	 * Open the socket into the kernel.
	 */
	if ((s = socket(AF_NETROM, SOCK_SEQPACKET, 0)) < 0) {
		sprintf(buffer, "ERROR: cannot open NET/ROM socket, %s\n", strerror(errno));
		fprintf(stderr, "%s\n", buffer);
		close(s);
		return (-1);
	}

	/*
	 * Set our AX.25 callsign and NET/ROM callsign accordingly.
	 */
	if (bind(s, (struct sockaddr *)&nrbind, addrlen) != 0) {
		sprintf(buffer, "ERROR: cannot bind NET/ROM socket, %s\n", strerror(errno));
		fprintf(stderr, "%s\n", buffer);
		close(s);
		return (-1);
	}

	/*
	 * Lets try and connect to the far end.
	 */
	if (connect(s, (struct sockaddr *)&nrconnect, addrlen) != 0) {
		sprintf(buffer,"\nTrying %s ", destcall);
		switch (errno) {
			case ECONNREFUSED:
				strcat(buffer, "*** Flexd: Connection refused - will try again later\n");
				break;
			case ENETUNREACH:
				strcat(buffer, "*** Flexd: Route is closed - will try again later\n");
				break;
			case EINTR:
				strcat(buffer, "*** Flexd: Connection timed out - will try again later\n");
				break;
			default:
				sprintf(buffer, "Flexd: ERROR cannot connect to NET/ROM node, %s\n", strerror(errno));
				break;
		}
		fprintf(stderr, "\nBUFFER:%s\n", buffer);
		close(s);
		return (1);
	}
	break;
	case AF_AX25:
		if (window == 0)
			window = ax25_config_get_window(port);
		if (paclen == 0)
			paclen = ax25_config_get_paclen(port);

		dlist[0] = gw->dest_call;
		if (dlist[0] == NULL) {
			fprintf(stderr,
				"flexd: too few arguments for AX.25\n");
			return (-1);
		}
		if ((s = socket(AF_AX25, SOCK_SEQPACKET, 0)) < 0) {
			perror("flexd: socket");
			return (-1);
		}
		ax25_aton(ax25_config_get_addr(port), &sockaddr.ax25);
		if (sockaddr.ax25.fsa_ax25.sax25_ndigis == 0) {
			ax25_aton_entry(ax25_config_get_addr(port),
					sockaddr.ax25.fsa_digipeater[0].
					ax25_call);
			sockaddr.ax25.fsa_ax25.sax25_ndigis = 1;
		}
		sockaddr.ax25.fsa_ax25.sax25_family = AF_AX25;
		addrlen = sizeof(struct full_sockaddr_ax25);

		if (setsockopt
		    (s, SOL_AX25, AX25_WINDOW, &window,
		     sizeof(window)) == -1) {
			perror("flexd: AX25_WINDOW");
			close(s);
			return (-1);
		}
		if (setsockopt
		    (s, SOL_AX25, AX25_PACLEN, &paclen,
		     sizeof(paclen)) == -1) {
			perror("flexd: AX25_PACLEN");
			close(s);
			return (-1);
		}
		if (backoff != -1) {
			if (setsockopt
			    (s, SOL_AX25, AX25_BACKOFF, &backoff,
			     sizeof(backoff)) == -1) {
				perror("flexd: AX25_BACKOFF");
				close(s);
				return (-1);
			}
		}
		if (ax25mode != -1) {
			if (setsockopt
			    (s, SOL_AX25, AX25_EXTSEQ, &ax25mode,
			     sizeof(ax25mode)) == -1) {
				perror("flexd: AX25_EXTSEQ");
				close(s);
				return (-1);
			}
		}
		if (ax25_aton_arglist
		    ((const char **) dlist, &sockaddr.ax25) == -1) {
			close(s);
			return (-1);
		}
	/*
	 * Open the socket into the kernel.
	 */
	if ((s = socket(AF_AX25, SOCK_SEQPACKET, 0)) < 0) {
		sprintf(buffer, "flexd connect: cannot open AX.25 socket, %s\n",
				strerror(errno));
		write(STDOUT_FILENO, buffer, strlen(buffer));
		return (-1);
	}

	/*
	 * Set our AX.25 callsign and AX.25 port callsign accordingly.
	 */
	if (*mycall == '\0')
		sprintf(buffer, "\n%s %s\n", addr, addr);
	else
		sprintf(buffer, "\n%s %s\n", mycall, addr);

	ax25_aton(buffer, &sockaddr.ax25);
	
	if (bind(s, (struct sockaddr *) &sockaddr, addrlen) != 0) {
		sprintf(buffer, "flexd connect: cannot bind AX.25 socket, %s\n",
				strerror(errno));
		write(STDOUT_FILENO, buffer, strlen(buffer));
		close(s);
		return (-1);
	}
	/*FSA*/
        sleep(1);
	/*FSA*/
	/*
	 * Lets try and connect to the far end.
	 *
	 */
	if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) {
		sprintf(buffer, "flexd connect: fcntl on socket: %s\n",
				strerror(errno));
		write(STDOUT_FILENO, buffer, strlen(buffer));
		close(s);
		return (-1);
	}

	if (ax25_aton_arglist((const char **) dlist, &sockaddr.ax25) == -1) {
		sprintf(buffer,
				"flexd connect: invalid destination callsign or digipeater\n");
		write(STDOUT_FILENO, buffer, strlen(buffer));
		close(s);
		return (-1);
	}

	/*FSA*/
        sleep(1);
	/*FSA*/
/**/
        if (connect(s, (struct sockaddr *) &sockaddr, addrlen) == -1
		&& errno != EINPROGRESS) {
		switch (errno) {
		case ECONNREFUSED:
			strcpy(buffer, "*** Flexd: Connection refused - will try again later\n");
			break;
		case ENETUNREACH:
			strcpy(buffer, "*** Flexd: Route is closed - will try again later\n");
			break;
		case EINTR:
			strcpy(buffer, "*** Flexd: Connection timed out - will try again later\n");
			break;
		default:
			sprintf(buffer, "*** Flexd: Cannot connect %s\n", strerror(errno));
			break;
		}

		write(STDOUT_FILENO, buffer, strlen(buffer));
		close(s);
		return (1);
	}
/**/
	break;
	}

	fflush(stdout);
/*
 * We got there.
 */
	while (1) {
		FD_ZERO(&read_fd);
		FD_SET(s, &read_fd);
		if (select(s + 1, &read_fd, NULL, 0, 0) == -1) {
                    break;
		}
		if (FD_ISSET(s, &read_fd)) {
                    /*	See if we got connected or if this was an error		*/
                    getsockopt(s, SOL_SOCKET, SO_ERROR, &ret, &retlen);

                    switch (af_mode) {
                        case AF_ROSE:
                            break;
                        case AF_NETROM:
                            break;
                        case AF_AX25: {
/*FSA don'know how but works!*/
                            if ((ret != 0) && (ret != 256)) {
                                cp = strdup(strerror(ret));
                                strlwr(cp);
                                sprintf(buffer, "flexd connect: Failure with %s error %d %s\n",
						gateway, ret, cp);
                                write(STDOUT_FILENO, buffer, strlen(buffer));
                                free(cp);
                                close(s);
                                return 1;
                            }
                        } break;
                        default:
                            break;
                    }
                    break;
		}
	}

	commands[0] = "d\r";
	commands[1] = "q\r";
	commands[2] = "b\r";
	commands[3] = NULL;

	/*
	 * Loop until one end of the connection goes away.
	 */

	if ((tmp = fopen(fname, "w")) == NULL) {
		fprintf(stderr, "flexd connect: Cannot open temporary file: %s\n",
				fname);
		close(s);
		return (-1);
	}
/*FSA*/
        sleep(1);
/*FSA*/
	for (;;) {
		int prompt = 0;
		FD_ZERO(&read_fd);
		FD_SET(s, &read_fd);
		if (select(s + 1, &read_fd, NULL, NULL, NULL) == -1) {
			break;
		}
		if (FD_ISSET(s, &read_fd)) {
			if ((n = read(s, buffer, 512)) == -1)
				break;
			for (c = 0; c < n; c++) {
				if (buffer[c] == '\r')
					buffer[c] = '\n';
				if ((c < n-1) && ((buffer[c] == '=') && (buffer[c + 1] == '>')
					|| (buffer[c] == '-' && (buffer[c + 1] == '>'))
				       	|| ((buffer[c] == ':')  && (buffer[c - 1] == ' ') && (buffer[c + 1] == ' ')))) {
					cmd_ack++;
				}
			}
			if (cmd_send > 0) {
				fwrite(buffer, sizeof(char), n, tmp);
			}
		}

		if (cmd_ack != 0) {
			if (cmd_send < 3) {
				write(s, commands[cmd_send], 2);
				cmd_send++;
			}
		}
	}
	close(s);
	fclose(tmp);
	return 0;
}
Example #18
0
/*
 * Process a route report for a single origin, creating or updating the
 * corresponding routing table entry if necessary.  'src' is either the
 * address of a neighboring router from which the report arrived, or zero
 * to indicate a change of status of one of our own interfaces.
 */
void
update_route(u_int32_t origin, u_int32_t mask, u_int metric, u_int32_t src,
             vifi_t vifi)
{
    register struct rtentry *r;
    u_int adj_metric;

    /*
     * Compute an adjusted metric, taking into account the cost of the
     * subnet or tunnel over which the report arrived, and normalizing
     * all unreachable/poisoned metrics into a single value.
     */
    if (src != 0 && (metric < 1 || metric >= 2*UNREACHABLE)) {
        logit(LOG_WARNING, 0,
              "%s reports out-of-range metric %u for origin %s",
              inet_fmt(src, s1), metric, inet_fmts(origin, mask, s2));
        return;
    }
    adj_metric = metric + uvifs[vifi].uv_metric;
    if (adj_metric > UNREACHABLE) adj_metric = UNREACHABLE;

    /*
     * Look up the reported origin in the routing table.
     */
    if (!find_route(origin, mask)) {
        /*
         * Not found.
         * Don't create a new entry if the report says it's unreachable,
         * or if the reported origin and mask are invalid.
         */
        if (adj_metric == UNREACHABLE) {
            return;
        }
        if (src != 0 && !inet_valid_subnet(origin, mask)) {
            logit(LOG_WARNING, 0,
                  "%s reports an invalid origin (%s) and/or mask (%08x)",
                  inet_fmt(src, s1), inet_fmt(origin, s2), ntohl(mask));
            return;
        }

        /*
         * OK, create the new routing entry.  'rtp' will be left pointing
         * to the new entry.
         */
        create_route(origin, mask);

        /*
         * Now "steal away" any sources that belong under this route
         * by deleting any cache entries they might have created
         * and allowing the kernel to re-request them.
         */
        steal_sources(rtp);

        rtp->rt_metric = UNREACHABLE;	/* temporary; updated below */
    }

    /*
     * We now have a routing entry for the reported origin.  Update it?
     */
    r = rtp;
    if (r->rt_metric == UNREACHABLE) {
        /*
         * The routing entry is for a formerly-unreachable or new origin.
         * If the report claims reachability, update the entry to use
         * the reported route.
         */
        if (adj_metric == UNREACHABLE)
            return;

        r->rt_parent   = vifi;
        init_children_and_leaves(r, vifi);

        r->rt_gateway  = src;
        r->rt_timer    = 0;
        r->rt_metric   = adj_metric;
        r->rt_flags   |= RTF_CHANGED;
        routes_changed = TRUE;
        update_table_entry(r);
    }
    else if (src == r->rt_gateway) {
        /*
         * The report has come either from the interface directly-connected
         * to the origin subnet (src and r->rt_gateway both equal zero) or
         * from the gateway we have chosen as the best first-hop gateway back
         * towards the origin (src and r->rt_gateway not equal zero).  Reset
         * the route timer and, if the reported metric has changed, update
         * our entry accordingly.
         */
        r->rt_timer = 0;
        if (adj_metric == r->rt_metric)
            return;

        if (adj_metric == UNREACHABLE) {
            del_table_entry(r, 0, DEL_ALL_ROUTES);
            r->rt_timer = ROUTE_EXPIRE_TIME;
        }
        else if (adj_metric < r->rt_metric) {
            if (init_children_and_leaves(r, vifi)) {
                update_table_entry(r);
            }
        }
        r->rt_metric   = adj_metric;
        r->rt_flags   |= RTF_CHANGED;
        routes_changed = TRUE;
    }
    else if (src == 0 ||
             (r->rt_gateway != 0 &&
              (adj_metric < r->rt_metric ||
               (adj_metric == r->rt_metric &&
                (ntohl(src) < ntohl(r->rt_gateway) ||
                 r->rt_timer >= ROUTE_SWITCH_TIME))))) {
        /*
         * The report is for an origin we consider reachable; the report
         * comes either from one of our own interfaces or from a gateway
         * other than the one we have chosen as the best first-hop gateway
         * back towards the origin.  If the source of the update is one of
         * our own interfaces, or if the origin is not a directly-connected
         * subnet and the reported metric for that origin is better than
         * what our routing entry says, update the entry to use the new
         * gateway and metric.  We also switch gateways if the reported
         * metric is the same as the one in the route entry and the gateway
         * associated with the route entry has not been heard from recently,
         * or if the metric is the same but the reporting gateway has a lower
         * IP address than the gateway associated with the route entry.
         * Did you get all that?
         */
        if (r->rt_parent != vifi || adj_metric < r->rt_metric) {
            /*
             * XXX Why do we do this if we are just changing the metric?
             */
            r->rt_parent = vifi;
            if (init_children_and_leaves(r, vifi)) {
                update_table_entry(r);
            }
        }
        r->rt_gateway  = src;
        r->rt_timer    = 0;
        r->rt_metric   = adj_metric;
        r->rt_flags   |= RTF_CHANGED;
        routes_changed = TRUE;
    }
    else if (vifi != r->rt_parent) {
        /*
         * The report came from a vif other than the route's parent vif.
         * Update the children and leaf info, if necessary.
         */
        if (VIFM_ISSET(vifi, r->rt_children)) {
            /*
             * Vif is a child vif for this route.
             */
            if (metric  < r->rt_metric ||
                    (metric == r->rt_metric &&
                     ntohl(src) < ntohl(uvifs[vifi].uv_lcl_addr))) {
                /*
                 * Neighbor has lower metric to origin (or has same metric
                 * and lower IP address) -- it becomes the dominant router,
                 * and vif is no longer a child for me.
                 */
                VIFM_CLR(vifi, r->rt_children);
                VIFM_CLR(vifi, r->rt_leaves);
                r->rt_dominants   [vifi] = src;
                r->rt_subordinates[vifi] = 0;
                r->rt_leaf_timers [vifi] = 0;
                update_table_entry(r);
            }
            else if (metric > UNREACHABLE) {	/* "poisoned reverse" */
                /*
                 * Neighbor considers this vif to be on path to route's
                 * origin; if no subordinate recorded, record this neighbor
                 * as subordinate and clear the leaf flag.
                 */
                if (r->rt_subordinates[vifi] == 0) {
                    VIFM_CLR(vifi, r->rt_leaves);
                    r->rt_subordinates[vifi] = src;
                    r->rt_leaf_timers [vifi] = 0;
                    update_table_entry(r);
                }
            }
            else if (src == r->rt_subordinates[vifi]) {
                /*
                 * Current subordinate no longer considers this vif to be on
                 * path to route's origin; it is no longer a subordinate
                 * router, and we set the leaf confirmation timer to give
                 * us time to hear from other subordinates.
                 */
                r->rt_subordinates[vifi] = 0;
                if (uvifs[vifi].uv_neighbors == NULL ||
                        uvifs[vifi].uv_neighbors->al_next == NULL) {
                    VIFM_SET(vifi, r->rt_leaves);
                    update_table_entry(r);
                }
                else {
                    r->rt_leaf_timers [vifi] = LEAF_CONFIRMATION_TIME;
                    r->rt_flags |= RTF_LEAF_TIMING;
                }
            }

        }
        else if (src == r->rt_dominants[vifi] &&
                 (metric  > r->rt_metric ||
                  (metric == r->rt_metric &&
                   ntohl(src) > ntohl(uvifs[vifi].uv_lcl_addr)))) {
            /*
             * Current dominant no longer has a lower metric to origin
             * (or same metric and lower IP address); we adopt the vif
             * as our own child.
             */
            VIFM_SET(vifi, r->rt_children);
            r->rt_dominants  [vifi] = 0;
            if (metric > UNREACHABLE) {
                r->rt_subordinates[vifi] = src;
            }
            else if (uvifs[vifi].uv_neighbors == NULL ||
                     uvifs[vifi].uv_neighbors->al_next == NULL) {
                VIFM_SET(vifi, r->rt_leaves);
            }
            else {
                r->rt_leaf_timers[vifi] = LEAF_CONFIRMATION_TIME;
                r->rt_flags |= RTF_LEAF_TIMING;
            }
            update_table_entry(r);
        }
    }
}
void find_route(int i, int j) {
    int i1, j1;
    if (grid[i][j] == 0) {
        grid[i][j] = 4;
        if (grid[i][j-1] < 4
            && j-1 >= 0
            && i < size_of_column - 1) {
            i1 = i;
            j1 = j-1;
            find_route(i1, j1);
        }
        if (grid[i-1][j] < 4
            && i-1 >= 0
            && j < size_of_line - 1) {
            i1 = i-1;
            j1 = j;
            find_route(i1, j1);
        }
        if (grid[i][j+1] < 2
            && j+1 < size_of_line
            && i < size_of_column - 1) {
            i1 = i;
            j1 = j+1;
            find_route(i1, j1);
        }
        if (i+1 < size_of_column
            && j < size_of_line - 1
            && (grid[i+1][j] == 0 || grid[i+1][j] == 2)) {
            i1 = i+1;
            j1 = j;
            find_route(i1, j1);
        }
    }
    if (grid[i][j] == 1) {
        grid[i][j] = 4;
        if (grid[i][j-1] < 4
            && j-1 >= 0
            && i < size_of_column - 1) {
            i1 = i;
            j1 = j-1;
            find_route(i1, j1);
        }
        if (grid[i][j+1] < 2
            && j+1 < size_of_line
            && i < size_of_column - 1) {
            i1 = i;
            j1 = j+1;
            find_route(i1, j1);
        }
        if ((grid[i+1][j] == 0 || grid[i+1][j] == 2)
            && i+1 < size_of_column
            && j < size_of_line - 1) {
            i1 = i+1;
            j1 = j;
            find_route(i1, j1);
        }
    }
    if (grid[i][j] == 2) {
        grid[i][j] = 4;
        if (grid[i-1][j] < 4
            && i-1 >= 0
            && j < size_of_line - 1) {
            i1 = i-1;
            j1 = j;
            find_route(i1, j1);
        }
        if (grid[i][j+1] < 2
            && j+1 < size_of_line
            && i < size_of_column - 1) {
            i1 = i;
            j1 = j+1;
            find_route(i1, j1);
        }
        if ((grid[i+1][j] == 0 || grid[i+1][j] == 2)
            && i+1 < size_of_column
            && j < size_of_line - 1) {
            i1 = i+1;
            j1 = j;
            find_route(i1, j1);
        }
    }
    if (grid[i][j] == 3) {
        grid[i][j] = 4;
        if (grid[i][j+1] < 2
            && j+1 < size_of_line
            && i < size_of_column - 1) {
            i1 = i;
            j1 = j+1;
            find_route(i1, j1);
        }
        if ((grid[i+1][j] == 0 || grid[i+1][j] == 2)
            && i+1 < size_of_column
            && j < size_of_line - 1) {
            i1 = i+1;
            j1 = j;
            find_route(i1, j1);
        }
    }
}
Example #20
0
File: server.C Project: Amit-DU/dht
void
vnode_impl::find_successor (const chordID &x, cbroute_t cb)
{
  nfindsuccessor++;
  find_route (x, wrap (mkref (this), &vnode_impl::find_successor_cb, x, cb));
}
Example #21
0
File: route.c Project: F0rth/pimd
/*
 * TODO: when cache miss, check the iif, because probably ASSERTS
 * shoult take place
 */
static void process_cache_miss(struct igmpmsg *igmpctl)
{
    u_int32 source, mfc_source;
    u_int32 group;
    u_int32 rp_addr;
    vifi_t iif;
    mrtentry_t *mrtentry_ptr;
    mrtentry_t *mrtentry_rp;

    /*
     * When there is a cache miss, we check only the header of the packet
     * (and only it should be sent up by the kernel.
     */

    group  = igmpctl->im_dst.s_addr;
    source = mfc_source = igmpctl->im_src.s_addr;
    iif    = igmpctl->im_vif;

    IF_DEBUG(DEBUG_MFC)
        logit(LOG_DEBUG, 0, "Cache miss, src %s, dst %s, iif %d",
              inet_fmt(source, s1, sizeof(s1)), inet_fmt(group, s2, sizeof(s2)), iif);

    /* TODO: XXX: check whether the kernel generates cache miss for the
     * LAN scoped addresses
     */
    if (ntohl(group) <= INADDR_MAX_LOCAL_GROUP)
        return; /* Don't create routing entries for the LAN scoped addresses */

    /* TODO: check if correct in case the source is one of my addresses */
    /* If I am the DR for this source, create (S,G) and add the register_vif
     * to the oifs.
     */
    if ((uvifs[iif].uv_flags & VIFF_DR)
        && (find_vif_direct_local(source) == iif)) {
        mrtentry_ptr = find_route(source, group, MRTF_SG, CREATE);
        if (mrtentry_ptr == (mrtentry_t *)NULL)
            return;
        mrtentry_ptr->flags &= ~MRTF_NEW;
        /* set reg_vif_num as outgoing interface ONLY if I am not the RP */
        if (mrtentry_ptr->group->rpaddr != my_cand_rp_address)
            VIFM_SET(reg_vif_num, mrtentry_ptr->joined_oifs);
        change_interfaces(mrtentry_ptr,
                          mrtentry_ptr->incoming,
                          mrtentry_ptr->joined_oifs,
                          mrtentry_ptr->pruned_oifs,
                          mrtentry_ptr->leaves,
                          mrtentry_ptr->asserted_oifs, 0);
    }
    else {
        mrtentry_ptr = find_route(source, group,
                                  MRTF_SG | MRTF_WC | MRTF_PMBR,
                                  DONT_CREATE);
        if (mrtentry_ptr == (mrtentry_t *)NULL)
            return;
    }

    /* TODO: if there are too many cache miss for the same (S,G), install
     * negative cache entry in the kernel (oif==NULL) to prevent too
     * many upcalls.
     */

    if (mrtentry_ptr->incoming == iif) {
        if (!VIFM_ISEMPTY(mrtentry_ptr->oifs)) {
            if (mrtentry_ptr->flags & MRTF_SG) {
                /* TODO: check that the RPbit is not set? */
                /* TODO: XXX: TIMER implem. dependency! */
                if (mrtentry_ptr->timer < PIM_DATA_TIMEOUT)
                    SET_TIMER(mrtentry_ptr->timer, PIM_DATA_TIMEOUT);
                if (!(mrtentry_ptr->flags & MRTF_SPT)) {
                    if ((mrtentry_rp = mrtentry_ptr->group->grp_route) ==
                        (mrtentry_t *)NULL)
                        mrtentry_rp = mrtentry_ptr->group->active_rp_grp->rp->rpentry->mrtlink;
                    if (mrtentry_rp != (mrtentry_t *)NULL) {
                        /* Check if the (S,G) iif is different from
                         * the (*,G) or (*,*,RP) iif
                         */
                        if ((mrtentry_ptr->incoming != mrtentry_rp->incoming)
                            || (mrtentry_ptr->upstream != mrtentry_rp->upstream)) {
                            mrtentry_ptr->flags |= MRTF_SPT;
                            mrtentry_ptr->flags &= ~MRTF_RP;
                        }
                    }
                }
            }
            if (mrtentry_ptr->flags & MRTF_PMBR)
                rp_addr = mrtentry_ptr->source->address;
            else
                rp_addr = mrtentry_ptr->group->rpaddr;
            mfc_source = source;
#ifdef KERNEL_MFC_WC_G
            if (mrtentry_ptr->flags & (MRTF_WC | MRTF_PMBR))
                if (!(mrtentry_ptr->flags & MRTF_MFC_CLONE_SG))
                    mfc_source = INADDR_ANY_N;
#endif /* KERNEL_MFC_WC_G */
            add_kernel_cache(mrtentry_ptr, mfc_source, group, MFC_MOVE_FORCE);
#ifdef SCOPED_ACL
            APPLY_SCOPE(group,mrtentry_ptr);
#endif
            k_chg_mfc(igmp_socket, mfc_source, group, iif, mrtentry_ptr->oifs,
                      rp_addr);
            /* TODO: XXX: No need for RSRR message, because nothing has
             * changed.
             */
        }

        return; /* iif match */
    }

    /* The iif doesn't match */
    if (mrtentry_ptr->flags & MRTF_SG) {
        if (mrtentry_ptr->flags & MRTF_SPT)
            /* Arrived on wrong interface */
            return;
        if ((mrtentry_rp = mrtentry_ptr->group->grp_route) ==
            (mrtentry_t *)NULL)
            mrtentry_rp =
                mrtentry_ptr->group->active_rp_grp->rp->rpentry->mrtlink;
        if (mrtentry_rp != (mrtentry_t *)NULL) {
            if (mrtentry_rp->incoming == iif) {
                /* Forward on (*,G) or (*,*,RP) */
#ifdef KERNEL_MFC_WC_G
                if (!(mrtentry_rp->flags & MRTF_MFC_CLONE_SG))
                    mfc_source = INADDR_ANY_N;
#endif /* KERNEL_MFC_WC_G */
                add_kernel_cache(mrtentry_rp, mfc_source, group, 0);
/* marian: not sure if we are going to reach here for our scoped traffic */
#ifdef SCOPED_ACL
                APPLY_SCOPE(group,mrtentry_ptr);
#endif
                k_chg_mfc(igmp_socket, mfc_source, group, iif,
                          mrtentry_rp->oifs, mrtentry_ptr->group->rpaddr);
#ifdef RSRR
                rsrr_cache_send(mrtentry_rp, RSRR_NOTIFICATION_OK);
#endif /* RSRR */
            }
        }

        return;
    }
}
Example #22
0
status_t
add_route(struct net_domain* _domain, const struct net_route* newRoute)
{
	struct net_domain_private* domain = (net_domain_private*)_domain;

	TRACE("add route to domain %s: dest %s, mask %s, gw %s, flags %lx\n",
		domain->name,
		AddressString(domain, newRoute->destination
			? newRoute->destination : NULL).Data(),
		AddressString(domain, newRoute->mask ? newRoute->mask : NULL).Data(),
		AddressString(domain, newRoute->gateway
			? newRoute->gateway : NULL).Data(),
		newRoute->flags);

	if (domain == NULL || newRoute == NULL
		|| newRoute->interface_address == NULL
		|| ((newRoute->flags & RTF_HOST) != 0 && newRoute->mask != NULL)
		|| ((newRoute->flags & RTF_DEFAULT) == 0
			&& newRoute->destination == NULL)
		|| ((newRoute->flags & RTF_GATEWAY) != 0 && newRoute->gateway == NULL)
		|| !domain->address_module->check_mask(newRoute->mask))
		return B_BAD_VALUE;

	RecursiveLocker _(domain->lock);

	net_route_private* route = find_route(domain, newRoute);
	if (route != NULL)
		return B_FILE_EXISTS;

	route = new (std::nothrow) net_route_private;
	if (route == NULL)
		return B_NO_MEMORY;

	if (domain->address_module->copy_address(newRoute->destination,
			&route->destination, (newRoute->flags & RTF_DEFAULT) != 0,
			newRoute->mask) != B_OK
		|| domain->address_module->copy_address(newRoute->mask, &route->mask,
			(newRoute->flags & RTF_DEFAULT) != 0, NULL) != B_OK
		|| domain->address_module->copy_address(newRoute->gateway,
			&route->gateway, false, NULL) != B_OK) {
		delete route;
		return B_NO_MEMORY;
	}

	route->flags = newRoute->flags;
	route->interface_address = newRoute->interface_address;
	((InterfaceAddress*)route->interface_address)->AcquireReference();
	route->mtu = 0;
	route->ref_count = 1;

	// Insert the route sorted by completeness of its mask

	RouteList::Iterator iterator = domain->routes.GetIterator();
	net_route_private* before = NULL;

	while ((before = iterator.Next()) != NULL) {
		// if the before mask is less specific than the one of the route,
		// we can insert it before that route.
		if (domain->address_module->first_mask_bit(before->mask)
				> domain->address_module->first_mask_bit(route->mask))
			break;

		if ((route->flags & RTF_DEFAULT) != 0
			&& (before->flags & RTF_DEFAULT) != 0) {
			// both routes are equal - let the link speed decide the
			// order
			if (before->interface_address->interface->device->link_speed
					< route->interface_address->interface->device->link_speed)
				break;
		}
	}

	domain->routes.Insert(before, route);
	update_route_infos(domain);

	return B_OK;
}
Example #23
0
File: route.c Project: F0rth/pimd
/*
 * TODO: XXX: currently `source` is not used. Will be used with IGMPv3 where
 * we have source-specific Join/Prune.
 */
void add_leaf(vifi_t vifi, u_int32 source __attribute__((unused)), u_int32 group)
{
    mrtentry_t *mrtentry_ptr;
    mrtentry_t *mrtentry_srcs;
    vifbitmap_t old_oifs;
    vifbitmap_t new_oifs;
    vifbitmap_t new_leaves;

    if (ntohl(group) <= INADDR_MAX_LOCAL_GROUP)
        return; /* Don't create routing entries for the LAN scoped addresses */

    /*
     * XXX: only if I am a DR, the IGMP Join should result in creating
     * a PIM MRT state.
     * XXX: Each router must know if it has local members, i.e., whether
     * it is a last-hop router as well. This info is needed so it will
     * know whether is allowed to initiate a SPT switch by sending
     * a PIM (S,G) Join to the high datarate source.
     * However, if a non-DR last-hop router has not received
     * a PIM Join, it should not create a PIM state, otherwise later
     * this state may incorrectly trigger PIM joins.
     * There is a design flow in pimd, so without making major changes
     * the best we can do is that the non-DR last-hop router will
     * record the local members only after it receives PIM Join from the DR
     * (i.e.  after the second or third IGMP Join by the local member).
     * The downside is that a last-hop router may delay the initiation
     * of the SPT switch. Sigh...
     */
    if (uvifs[vifi].uv_flags & VIFF_DR)
        mrtentry_ptr = find_route(INADDR_ANY_N, group, MRTF_WC, CREATE);
    else
        mrtentry_ptr = find_route(INADDR_ANY_N, group, MRTF_WC, DONT_CREATE);

    if (mrtentry_ptr == (mrtentry_t *)NULL)
        return;

    IF_DEBUG(DEBUG_MRT)
        logit(LOG_DEBUG, 0, "Adding vif %d for group %s", vifi,
              inet_fmt(group, s1, sizeof(s1)));

    if (VIFM_ISSET(vifi, mrtentry_ptr->leaves))
        return;     /* Already a leaf */
    calc_oifs(mrtentry_ptr, &old_oifs);
    VIFM_COPY(mrtentry_ptr->leaves, new_leaves);
    VIFM_SET(vifi, new_leaves);    /* Add the leaf */
    change_interfaces(mrtentry_ptr,
                      mrtentry_ptr->incoming,
                      mrtentry_ptr->joined_oifs,
                      mrtentry_ptr->pruned_oifs,
                      new_leaves,
                      mrtentry_ptr->asserted_oifs, 0);
    calc_oifs(mrtentry_ptr, &new_oifs);

    /* Only if I am the DR for that subnet, eventually initiate a Join */
    if (!(uvifs[vifi].uv_flags & VIFF_DR))
        return;

    if ((mrtentry_ptr->flags & MRTF_NEW)
        || (VIFM_ISEMPTY(old_oifs) && (!VIFM_ISEMPTY(new_oifs)))) {
        /* A new created entry or the oifs have changed
         * from NULL to non-NULL.
         */
        mrtentry_ptr->flags &= ~MRTF_NEW;
        FIRE_TIMER(mrtentry_ptr->jp_timer); /* Timeout the Join/Prune timer */
        /* TODO: explicitly call the function below?
           send_pim_join_prune(mrtentry_ptr->upstream->vifi,
           mrtentry_ptr->upstream,
           PIM_JOIN_PRUNE_HOLDTIME);
        */
    }

    /* Check all (S,G) entries and set the inherited "leaf" flag.
     * TODO: XXX: This won't work for IGMPv3, because there we don't know
     * whether the (S,G) leaf oif was inherited from the (*,G) entry or
     * was created by source specific IGMP join.
     */
    for (mrtentry_srcs = mrtentry_ptr->group->mrtlink;
         mrtentry_srcs != (mrtentry_t *)NULL;
         mrtentry_srcs = mrtentry_srcs->grpnext) {
        VIFM_COPY(mrtentry_srcs->leaves, new_leaves);
        VIFM_SET(vifi, new_leaves);
        change_interfaces(mrtentry_srcs,
                          mrtentry_srcs->incoming,
                          mrtentry_srcs->joined_oifs,
                          mrtentry_srcs->pruned_oifs,
                          new_leaves,
                          mrtentry_srcs->asserted_oifs, 0);
    }
}
void walk_character(int chac,int tox,int toy,int ignwal, bool autoWalkAnims) {
  CharacterInfo*chin=&game.chars[chac];
  if (chin->room!=displayed_room)
    quit("!MoveCharacter: character not in current room");

  chin->flags &= ~CHF_MOVENOTWALK;

  int toxPassedIn = tox, toyPassedIn = toy;
  int charX = convert_to_low_res(chin->x);
  int charY = convert_to_low_res(chin->y);
  tox = convert_to_low_res(tox);
  toy = convert_to_low_res(toy);

  if ((tox == charX) && (toy == charY)) {
    StopMoving(chac);
    DEBUG_CONSOLE("%s already at destination, not moving", chin->scrname);
    return;
  }

  if ((chin->animating) && (autoWalkAnims))
    chin->animating = 0;

  if (chin->idleleft < 0) {
    ReleaseCharacterView(chac);
    chin->idleleft=chin->idletime;
  }
  // stop them to make sure they're on a walkable area
  // but save their frame first so that if they're already
  // moving it looks smoother
  int oldframe = chin->frame;
  int waitWas = 0, animWaitWas = 0;
  // if they are currently walking, save the current Wait
  if (chin->walking)
  {
    waitWas = chin->walkwait;
    animWaitWas = charextra[chac].animwait;
  }

  StopMoving (chac);
  chin->frame = oldframe;
  // use toxPassedIn cached variable so the hi-res co-ordinates
  // are still displayed as such
  DEBUG_CONSOLE("%s: Start move to %d,%d", chin->scrname, toxPassedIn, toyPassedIn);

  int move_speed_x = chin->walkspeed;
  int move_speed_y = chin->walkspeed;

  if (chin->walkspeed_y != UNIFORM_WALK_SPEED)
    move_speed_y = chin->walkspeed_y;

  if ((move_speed_x == 0) && (move_speed_y == 0)) {
    debug_log("Warning: MoveCharacter called for '%s' with walk speed 0", chin->name);
  }

  set_route_move_speed(move_speed_x, move_speed_y);
  set_color_depth(8);
  int mslot=find_route(charX, charY, tox, toy, prepare_walkable_areas(chac), chac+CHMLSOFFS, 1, ignwal);
  set_color_depth(final_col_dep);
  if (mslot>0) {
    chin->walking = mslot;
    mls[mslot].direct = ignwal;

    if ((game.options[OPT_NATIVECOORDINATES] != 0) &&
        (game.default_resolution > 2))
    {
      convert_move_path_to_high_res(&mls[mslot]);
    }
    // cancel any pending waits on current animations
    // or if they were already moving, keep the current wait - 
    // this prevents a glitch if MoveCharacter is called when they
    // are already moving
    if (autoWalkAnims)
    {
      chin->walkwait = waitWas;
      charextra[chac].animwait = animWaitWas;

      if (mls[mslot].pos[0] != mls[mslot].pos[1]) {
        fix_player_sprite(&mls[mslot],chin);
      }
    }
    else
      chin->flags |= CHF_MOVENOTWALK;
  }
  else if (autoWalkAnims) // pathfinder couldn't get a route, stand them still
    chin->frame = 0;
}
Example #25
0
File: flexd.c Project: ve7fet/fpac
int read_conf(void)
{
	FILE *fp, *fgt;
	char buf[512], line[1024], *cp;
	int i = 0, k;
	char digipath[AX25_MAX_DIGIS * 10];
	if ((fp = fopen(FLEXD_CONF_FILE, "r")) == NULL) {
		fprintf(stderr, "flexd config: Cannot open config file: %s\n",
				FLEXD_CONF_FILE);
		return -1;
	}
	if ((fgt = fopen(FLEX_GT_FILE, "w")) == NULL) {
		fprintf(stderr,
				"flexd config: Cannot open flexnet gateways file: %s\n",
				FLEX_GT_FILE);
		fclose(fp);
		return -1;
	}

	fputs("addr  callsign  dev  digipeaters\n", fgt);

	while (fgets(buf, sizeof(buf), fp)) {
		if (*buf == '#' || *buf == ' ')
			continue;			/* comment line/empty line */
		cp = strchr(buf, '#');
		if (cp)
			*cp = '\0';
		cp = strtok(buf, " \t\n\r");
		if (cp == NULL)
			continue;			/* empty line */

		if (strcasecmp(cp, "pollinterval") == 0) {	/* set poll interval */
			cp = strtok(NULL, " \t\n\r");
			if (cp == NULL) {
				fprintf(stderr,
						"flexd config: PollInterval needs an argument\n");
				fclose(fp);
				fclose(fgt);
				return -1;
			}
			poll_time = safe_atoi(cp);
			if (poll_time < MINIMUM_POLL_TIME)
				poll_time = MINIMUM_POLL_TIME;
		}
		if (strcasecmp(cp, "mycall") == 0) {	/* set connect call for download */
			cp = strtok(NULL, " \t\n\r");
			if (cp == NULL) {
				fprintf(stderr,
						"flexd config: MyCall needs an argument\n");
				fclose(fp);
				fclose(fgt);
				return -1;
			}
			safe_strncpy(mycall, cp, 9);
		}
		if (strcasecmp(cp, "flexgate") == 0) {	/* set flexnet gateway */
			cp = strtok(NULL, " \t\n\r");
			if (cp == NULL) {
				fprintf(stderr,
						"flexd config: FlexGate needs an argument\n");
				fclose(fp);
				fclose(fgt);
				return -1;
			}
			safe_strncpy(flexgate, cp, 9);
/*	strcat(cp,"\0");*/
			gw = find_route(flexgate, NULL);
			if (gw == NULL) {
				fprintf(stderr,
						"flexd config: FlexGate %s not found in file: %s\n",
						flexgate, AX_ROUTES_FILE);
				fclose(fp);
				fclose(fgt);
				return -1;
			} else {
				*digipath = '\0';
				for (k = 0; k < AX25_MAX_DIGIS; k++) {
					if (gw->digis[k] == NULL)
						break;
					strcat(digipath, " ");
					strcat(digipath, gw->digis[k]);
				}
                                if ((ax25_config_get_dev(gw->dev)) == NULL )
                                    sprintf(line, "%05d %-8s %5s %s\n",i++, gw->dest_call, gw->dev, digipath);
				else
                                    /* ax25 device */
                                    sprintf(line, "%05d %-8s %4s %s\n",i++, gw->dest_call, ax25_config_get_dev(gw->dev), digipath);
                                fputs(line, fgt);
			}
		}
	}
	fclose(fgt);
	fclose(fp);
return 0;
}
Example #26
0
/*
 * Traceroute function which returns traceroute replies to the requesting
 * router. Also forwards the request to downstream routers.
 */
void accept_mtrace(u_int32 src, u_int32 dst, u_int32 group, char *data, u_int no, int datalen)
{
    u_char type;
    mrtentry_t *mrt;
    struct tr_query *qry;
    struct tr_resp  *resp;
    int vifi;
    char *p;
    u_int rcount;
    int errcode = TR_NO_ERR;
    int resptype;
    struct timeval tp;
    struct sioc_vif_req v_req;
#if 0
    /* TODO */
    struct sioc_sg_req sg_req;
#endif /* 0 */
    u_int32 parent_address = INADDR_ANY;

    /* Remember qid across invocations */
    static u_int32 oqid = 0;

    /* timestamp the request/response */
    gettimeofday(&tp, 0);

    /*
     * Check if it is a query or a response
     */
    if (datalen == QLEN) {
        type = QUERY;
        IF_DEBUG(DEBUG_TRACE)
            logit(LOG_DEBUG, 0, "Initial traceroute query rcvd from %s to %s",
                  inet_fmt(src, s1, sizeof(s1)), inet_fmt(dst, s2, sizeof(s2)));
    }
    else if ((datalen - QLEN) % RLEN == 0) {
        type = RESP;
        IF_DEBUG(DEBUG_TRACE)
            logit(LOG_DEBUG, 0, "In-transit traceroute query rcvd from %s to %s",
                  inet_fmt(src, s1, sizeof(s1)), inet_fmt(dst, s2, sizeof(s2)));
        if (IN_MULTICAST(ntohl(dst))) {
            IF_DEBUG(DEBUG_TRACE)
                logit(LOG_DEBUG, 0, "Dropping multicast response");
            return;
        }
    }
    else {
        logit(LOG_WARNING, 0, "%s from %s to %s",
              "Non decipherable traceroute request recieved",
              inet_fmt(src, s1, sizeof(s1)), inet_fmt(dst, s2, sizeof(s2)));
        return;
    }

    qry = (struct tr_query *)data;

    /*
     * if it is a packet with all reports filled, drop it
     */
    if ((rcount = (datalen - QLEN)/RLEN) == no) {
        IF_DEBUG(DEBUG_TRACE)
            logit(LOG_DEBUG, 0, "packet with all reports filled in");
        return;
    }

    IF_DEBUG(DEBUG_TRACE) {
        logit(LOG_DEBUG, 0, "s: %s g: %s d: %s ", inet_fmt(qry->tr_src, s1, sizeof(s1)),
              inet_fmt(group, s2, sizeof(s2)), inet_fmt(qry->tr_dst, s3, sizeof(s3)));
        logit(LOG_DEBUG, 0, "rttl: %d rd: %s", qry->tr_rttl,
              inet_fmt(qry->tr_raddr, s1, sizeof(s1)));
        logit(LOG_DEBUG, 0, "rcount:%d, qid:%06x", rcount, qry->tr_qid);
    }

    /* determine the routing table entry for this traceroute */
    mrt = find_route(qry->tr_src, group, MRTF_SG | MRTF_WC | MRTF_PMBR,
                     DONT_CREATE);
    IF_DEBUG(DEBUG_TRACE) {
        if (mrt != (mrtentry_t *)NULL) {
            if (mrt->upstream != (pim_nbr_entry_t *)NULL)
                parent_address = mrt->upstream->address;
            else
                parent_address = INADDR_ANY;
            logit(LOG_DEBUG, 0, "mrt parent vif: %d rtr: %s metric: %d",
                  mrt->incoming, inet_fmt(parent_address, s1, sizeof(s1)), mrt->metric);
/* TODO
   logit(LOG_DEBUG, 0, "mrt origin %s",
   RT_FMT(rt, s1));
*/
        } else {
            logit(LOG_DEBUG, 0, "...no route");
        }
    }

    /*
     * Query type packet - check if rte exists
     * Check if the query destination is a vif connected to me.
     * and if so, whether I should start response back
     */
    if (type == QUERY) {
        if (oqid == qry->tr_qid) {
            /*
             * If the multicast router is a member of the group being
             * queried, and the query is multicasted, then the router can
             * recieve multiple copies of the same query.  If we have already
             * replied to this traceroute, just ignore it this time.
             *
             * This is not a total solution, but since if this fails you
             * only get N copies, N <= the number of interfaces on the router,
             * it is not fatal.
             */
            IF_DEBUG(DEBUG_TRACE)
                logit(LOG_DEBUG, 0, "ignoring duplicate traceroute packet");
            return;
        }

        if (mrt == (mrtentry_t *)NULL) {
            IF_DEBUG(DEBUG_TRACE)
                logit(LOG_DEBUG, 0, "Mcast traceroute: no route entry %s",
                      inet_fmt(qry->tr_src, s1, sizeof(s1)));
            if (IN_MULTICAST(ntohl(dst)))
                return;
        }
        vifi = find_vif_direct(qry->tr_dst);

        if (vifi == NO_VIF) {
            /* The traceroute destination is not on one of my subnet vifs. */
            IF_DEBUG(DEBUG_TRACE)
                logit(LOG_DEBUG, 0, "Destination %s not an interface",
                      inet_fmt(qry->tr_dst, s1, sizeof(s1)));
            if (IN_MULTICAST(ntohl(dst)))
                return;
            errcode = TR_WRONG_IF;
        } else if (mrt != (mrtentry_t *)NULL && !VIFM_ISSET(vifi, mrt->oifs)) {
            IF_DEBUG(DEBUG_TRACE)
                logit(LOG_DEBUG, 0,
                      "Destination %s not on forwarding tree for src %s",
                      inet_fmt(qry->tr_dst, s1, sizeof(s1)), inet_fmt(qry->tr_src, s2, sizeof(s2)));
            if (IN_MULTICAST(ntohl(dst)))
                return;
            errcode = TR_WRONG_IF;
        }
    }
    else {
        /*
         * determine which interface the packet came in on
         * RESP packets travel hop-by-hop so this either traversed
         * a tunnel or came from a directly attached mrouter.
         */
        if ((vifi = find_vif_direct(src)) == NO_VIF) {
            IF_DEBUG(DEBUG_TRACE)
                logit(LOG_DEBUG, 0, "Wrong interface for packet");
            errcode = TR_WRONG_IF;
        }
    }

    /* Now that we've decided to send a response, save the qid */
    oqid = qry->tr_qid;

    IF_DEBUG(DEBUG_TRACE)
        logit(LOG_DEBUG, 0, "Sending traceroute response");

    /* copy the packet to the sending buffer */
    p = igmp_send_buf + IP_IGMP_HEADER_LEN + IGMP_MINLEN;

    bcopy(data, p, datalen);

    p += datalen;

    /*
     * If there is no room to insert our reply, coopt the previous hop
     * error indication to relay this fact.
     */
    if (p + sizeof(struct tr_resp) > igmp_send_buf + SEND_BUF_SIZE) {
        resp = (struct tr_resp *)p - 1;
        resp->tr_rflags = TR_NO_SPACE;
        mrt = NULL;
        goto sendit;
    }

    /*
     * fill in initial response fields
     */
    resp = (struct tr_resp *)p;
    memset(resp, 0, sizeof(struct tr_resp));
    datalen += RLEN;

    resp->tr_qarr    = htonl(((tp.tv_sec + JAN_1970) << 16) +
			     ((tp.tv_usec << 10) / 15625));
    resp->tr_rproto  = PROTO_PIM;
    resp->tr_outaddr = (vifi == NO_VIF) ? dst : uvifs[vifi].uv_lcl_addr;
    resp->tr_fttl    = (vifi == NO_VIF) ? 0   : uvifs[vifi].uv_threshold;
    resp->tr_rflags  = errcode;

    /*
     * obtain # of packets out on interface
     */
    v_req.vifi = vifi;
    if (vifi != NO_VIF && ioctl(udp_socket, SIOCGETVIFCNT, (char *)&v_req) >= 0)
        resp->tr_vifout  =  htonl(v_req.ocount);
    else
        resp->tr_vifout  =  0xffffffff;

    /*
     * fill in scoping & pruning information
     */
/* TODO */
#if 0
    if (mrt != (mrtentry_t *)NULL)
        for (gt = rt->rt_groups; gt; gt = gt->gt_next) {
            if (gt->gt_mcastgrp >= group)
                break;
        }
    else
        gt = NULL;

    if (gt && gt->gt_mcastgrp == group) {
        struct stable *st;

        for (st = gt->gt_srctbl; st; st = st->st_next)
            if (qry->tr_src == st->st_origin)
                break;

        sg_req.src.s_addr = qry->tr_src;
        sg_req.grp.s_addr = group;
        if (st && st->st_ctime != 0 &&
            ioctl(udp_socket, SIOCGETSGCNT, (char *)&sg_req) >= 0)
            resp->tr_pktcnt = htonl(sg_req.pktcnt + st->st_savpkt);
        else
            resp->tr_pktcnt = htonl(st ? st->st_savpkt : 0xffffffff);

        if (VIFM_ISSET(vifi, gt->gt_scope))
            resp->tr_rflags = TR_SCOPED;
        else if (gt->gt_prsent_timer)
            resp->tr_rflags = TR_PRUNED;
        else if (!VIFM_ISSET(vifi, gt->gt_grpmems))
            if (VIFM_ISSET(vifi, rt->rt_children) &&
                NBRM_ISSETMASK(uvifs[vifi].uv_nbrmap, rt->rt_subordinates)) /*XXX*/
                resp->tr_rflags = TR_OPRUNED;
            else
                resp->tr_rflags = TR_NO_FWD;
    } else {
        if (scoped_addr(vifi, group))
            resp->tr_rflags = TR_SCOPED;
        else if (rt && !VIFM_ISSET(vifi, rt->rt_children))
            resp->tr_rflags = TR_NO_FWD;
    }
#endif /* 0 */

    /*
     *  if no rte exists, set NO_RTE error
     */
    if (mrt == (mrtentry_t *)NULL) {
        src = dst;		/* the dst address of resp. pkt */
        resp->tr_inaddr   = 0;
        resp->tr_rflags   = TR_NO_RTE;
        resp->tr_rmtaddr  = 0;
    } else {
        /* get # of packets in on interface */
        v_req.vifi = mrt->incoming;
        if (ioctl(udp_socket, SIOCGETVIFCNT, (char *)&v_req) >= 0)
            resp->tr_vifin = htonl(v_req.icount);
        else
            resp->tr_vifin = 0xffffffff;

        /* TODO
           MASK_TO_VAL(rt->rt_originmask, resp->tr_smask);
        */
        src = uvifs[mrt->incoming].uv_lcl_addr;
        resp->tr_inaddr = src;
        if (mrt->upstream != (pim_nbr_entry_t *)NULL)
            parent_address = mrt->upstream->address;
        else
            parent_address = INADDR_ANY;

        resp->tr_rmtaddr = parent_address;
        if (!VIFM_ISSET(vifi, mrt->oifs)) {
            IF_DEBUG(DEBUG_TRACE)
                logit(LOG_DEBUG, 0, "Destination %s not on forwarding tree for src %s",
                      inet_fmt(qry->tr_dst, s1, sizeof(s1)), inet_fmt(qry->tr_src, s2, sizeof(s2)));
            resp->tr_rflags = TR_WRONG_IF;
        }
#if 0
        if (rt->rt_metric >= UNREACHABLE) {
            resp->tr_rflags = TR_NO_RTE;
            /* Hack to send reply directly */
            rt = NULL;
        }
#endif /* 0 */
    }

  sendit:
    /*
     * if metric is 1 or no. of reports is 1, send response to requestor
     * else send to upstream router.  If the upstream router can't handle
     * mtrace, set an error code and send to requestor anyway.
     */
    IF_DEBUG(DEBUG_TRACE)
        logit(LOG_DEBUG, 0, "rcount:%d, no:%d", rcount, no);

    if ((rcount + 1 == no) || (mrt == NULL) || (mrt->metric == 1)) {
        resptype = IGMP_MTRACE_RESP;
        dst = qry->tr_raddr;
    } else

#if 0   /* TODO */
    if (!can_mtrace(rt->rt_parent, rt->rt_gateway)) {
        dst = qry->tr_raddr;
        resp->tr_rflags = TR_OLD_ROUTER;
        resptype = IGMP_MTRACE_RESP;
    } else {
#endif  /* 0 */
        if (mrt->upstream != (pim_nbr_entry_t *)NULL)
            parent_address = mrt->upstream->address;
        else
            parent_address = INADDR_ANY;
        dst = parent_address;
        resptype = IGMP_MTRACE;
#if 0   /* TODO */
    }
#endif
    if (IN_MULTICAST(ntohl(dst))) {
	/*
	 * Send the reply on a known multicast capable vif.
	 * If we don't have one, we can't source any multicasts anyway.
	 */
	if (phys_vif != -1) {
	    IF_DEBUG(DEBUG_TRACE)
		logit(LOG_DEBUG, 0, "Sending reply to %s from %s",
		      inet_fmt(dst, s1, sizeof(s1)),
		      inet_fmt(uvifs[phys_vif].uv_lcl_addr, s2, sizeof(s2)));
	    k_set_ttl(igmp_socket, qry->tr_rttl);
	    send_igmp(igmp_send_buf, uvifs[phys_vif].uv_lcl_addr, dst,
		      resptype, no, group, datalen);
	    k_set_ttl(igmp_socket, 1);
	} else
	    logit(LOG_INFO, 0, "No enabled phyints -- %s",
		  "dropping traceroute reply");
    } else {
	IF_DEBUG(DEBUG_TRACE)
	    logit(LOG_DEBUG, 0, "Sending %s to %s from %s",
		  resptype == IGMP_MTRACE_RESP ?  "reply" : "request on",
		  inet_fmt(dst, s1, sizeof(s1)), inet_fmt(src, s2, sizeof(s2)));

	send_igmp(igmp_send_buf, src, dst, resptype, no, group, datalen);
    }
}