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; }
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; }
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)); }
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; }
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; }
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); } } }
/* 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(); }
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; }
/* * 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); } }
/* * 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; } }
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); } }
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; }
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; }
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; }
/* * 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); } } }
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)); }
/* * 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; } }
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; }
/* * 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; }
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; }
/* * 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); } }