int ax25_rt_get_info(char *buffer, char **start, off_t offset, int length, int dummy) { ax25_route *ax25_rt; int len = 0; off_t pos = 0; off_t begin = 0; char *callsign; int i; cli(); len += sprintf(buffer, "callsign dev mode digipeaters\n"); for (ax25_rt = ax25_route_list; ax25_rt != NULL; ax25_rt = ax25_rt->next) { if (ax25cmp(&ax25_rt->callsign, &null_ax25_address) == 0) callsign = "default"; else callsign = ax2asc(&ax25_rt->callsign); len += sprintf(buffer + len, "%-9s %-4s", callsign, ax25_rt->dev ? ax25_rt->dev->name : "???"); switch (ax25_rt->ip_mode) { case 'V': len += sprintf(buffer + len, " vc"); break; case 'D': len += sprintf(buffer + len, " dg"); break; default: len += sprintf(buffer + len, " *"); break; } if (ax25_rt->digipeat != NULL) for (i = 0; i < ax25_rt->digipeat->ndigi; i++) len += sprintf(buffer + len, " %s", ax2asc(&ax25_rt->digipeat->calls[i])); len += sprintf(buffer + len, "\n"); pos = begin + len; if (pos < offset) { len = 0; begin = pos; } if (pos > offset + length) break; } sti(); *start = buffer + (offset - begin); len -= (offset - begin); if (len > length) len = length; return len; }
int nr_neigh_get_info(char *buffer, char **start, off_t offset, int length) { struct nr_neigh *nr_neigh; int len = 0; off_t pos = 0; off_t begin = 0; int i; cli(); len += sprintf(buffer, "addr callsign dev qual lock count failed digipeaters\n"); for (nr_neigh = nr_neigh_list; nr_neigh != NULL; nr_neigh = nr_neigh->next) { len += sprintf(buffer + len, "%05d %-9s %-4s %3d %d %3d %3d", nr_neigh->number, ax2asc(&nr_neigh->callsign), nr_neigh->dev ? nr_neigh->dev->name : "???", nr_neigh->quality, nr_neigh->locked, nr_neigh->count, nr_neigh->failed); if (nr_neigh->digipeat != NULL) { for (i = 0; i < nr_neigh->digipeat->ndigi; i++) len += sprintf(buffer + len, " %s", ax2asc(&nr_neigh->digipeat->calls[i])); } len += sprintf(buffer + len, "\n"); pos = begin + len; if (pos < offset) { len = 0; begin = pos; } if (pos > offset + length) break; } sti(); *start = buffer + (offset - begin); len -= (offset - begin); if (len > length) len = length; return len; }
int ax25_uid_get_info(char *buffer, char **start, off_t offset, int length) { ax25_uid_assoc *pt; int len = 0; off_t pos = 0; off_t begin = 0; cli(); len += sprintf(buffer, "Policy: %d\n", ax25_uid_policy); for (pt = ax25_uid_list; pt != NULL; pt = pt->next) { len += sprintf(buffer + len, "%6d %s\n", pt->uid, ax2asc(&pt->call)); pos = begin + len; if (pos < offset) { len = 0; begin = pos; } if (pos > offset + length) break; } sti(); *start = buffer + (offset - begin); len -= offset - begin; if (len > length) len = length; return len; }
static int ax25_rt_seq_show(struct seq_file *seq, void *v) { char buf[11]; if (v == SEQ_START_TOKEN) seq_puts(seq, "callsign dev mode digipeaters\n"); else { struct ax25_route *ax25_rt = v; const char *callsign; int i; if (ax25cmp(&ax25_rt->callsign, &null_ax25_address) == 0) callsign = "default"; else callsign = ax2asc(buf, &ax25_rt->callsign); seq_printf(seq, "%-9s %-4s", callsign, ax25_rt->dev ? ax25_rt->dev->name : "???"); switch (ax25_rt->ip_mode) { case 'V': seq_puts(seq, " vc"); break; case 'D': seq_puts(seq, " dg"); break; default: seq_puts(seq, " *"); break; } if (ax25_rt->digipeat != NULL) for (i = 0; i < ax25_rt->digipeat->ndigi; i++) seq_printf(seq, " %s", ax2asc(buf, &ax25_rt->digipeat->calls[i])); seq_puts(seq, "\n"); } return 0; }
int nr_nodes_get_info(char *buffer, char **start, off_t offset, int length) { struct nr_node *nr_node; int len = 0; off_t pos = 0; off_t begin = 0; int i; cli(); len += sprintf(buffer, "callsign mnemonic w n qual obs neigh qual obs neigh qual obs neigh\n"); for (nr_node = nr_node_list; nr_node != NULL; nr_node = nr_node->next) { len += sprintf(buffer + len, "%-9s %-7s %d %d", ax2asc(&nr_node->callsign), (nr_node->mnemonic[0] == '\0') ? "*" : nr_node->mnemonic, nr_node->which + 1, nr_node->count); for (i = 0; i < nr_node->count; i++) { len += sprintf(buffer + len, " %3d %d %05d", nr_node->routes[i].quality, nr_node->routes[i].obs_count, nr_node->routes[i].neighbour->number); } len += sprintf(buffer + len, "\n"); pos = begin + len; if (pos < offset) { len = 0; begin = pos; } if (pos > offset + length) break; } sti(); *start = buffer + (offset - begin); len -= (offset - begin); if (len > length) len = length; return len; }
/* * Route a frame to an appropriate AX.25 connection. */ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) { struct rose_neigh *rose_neigh, *new_neigh; struct rose_route *rose_route; struct rose_facilities_struct facilities; rose_address *src_addr, *dest_addr; struct sock *sk; unsigned short frametype; unsigned int lci, new_lci; unsigned char cause, diagnostic; struct net_device *dev; int len, res = 0; #if 0 if (call_in_firewall(PF_ROSE, skb->dev, skb->data, NULL, &skb) != FW_ACCEPT) return res; #endif frametype = skb->data[2]; lci = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF); src_addr = (rose_address *)(skb->data + 9); dest_addr = (rose_address *)(skb->data + 4); spin_lock_bh(&rose_node_list_lock); spin_lock_bh(&rose_neigh_list_lock); spin_lock_bh(&rose_route_list_lock); rose_neigh = rose_neigh_list; while (rose_neigh != NULL) { if (ax25cmp(&ax25->dest_addr, &rose_neigh->callsign) == 0 && ax25->ax25_dev->dev == rose_neigh->dev) break; rose_neigh = rose_neigh->next; } if (rose_neigh == NULL) { printk("rose_route : unknown neighbour or device %s\n", ax2asc(&ax25->dest_addr)); goto out; } /* * Obviously the link is working, halt the ftimer. */ rose_stop_ftimer(rose_neigh); /* * LCI of zero is always for us, and its always a restart * frame. */ if (lci == 0) { rose_link_rx_restart(skb, rose_neigh, frametype); goto out; } /* * Find an existing socket. */ if ((sk = rose_find_socket(lci, rose_neigh)) != NULL) { if (frametype == ROSE_CALL_REQUEST) { struct rose_sock *rose = rose_sk(sk); /* Remove an existing unused socket */ rose_clear_queues(sk); rose->cause = ROSE_NETWORK_CONGESTION; rose->diagnostic = 0; rose->neighbour->use--; rose->neighbour = NULL; rose->lci = 0; rose->state = ROSE_STATE_0; sk->sk_state = TCP_CLOSE; sk->sk_err = 0; sk->sk_shutdown |= SEND_SHUTDOWN; if (!sock_flag(sk, SOCK_DEAD)) { sk->sk_state_change(sk); sock_set_flag(sk, SOCK_DEAD); } } else { skb->h.raw = skb->data; res = rose_process_rx_frame(sk, skb); goto out; } } /* * Is is a Call Request and is it for us ? */ if (frametype == ROSE_CALL_REQUEST) if ((dev = rose_dev_get(dest_addr)) != NULL) { res = rose_rx_call_request(skb, dev, rose_neigh, lci); dev_put(dev); goto out; } if (!sysctl_rose_routing_control) { rose_transmit_clear_request(rose_neigh, lci, ROSE_NOT_OBTAINABLE, 0); goto out; } /* * Route it to the next in line if we have an entry for it. */ rose_route = rose_route_list; while (rose_route != NULL) { if (rose_route->lci1 == lci && rose_route->neigh1 == rose_neigh) { if (frametype == ROSE_CALL_REQUEST) { /* F6FBB - Remove an existing unused route */ rose_remove_route(rose_route); break; } else if (rose_route->neigh2 != NULL) { skb->data[0] &= 0xF0; skb->data[0] |= (rose_route->lci2 >> 8) & 0x0F; skb->data[1] = (rose_route->lci2 >> 0) & 0xFF; rose_transmit_link(skb, rose_route->neigh2); if (frametype == ROSE_CLEAR_CONFIRMATION) rose_remove_route(rose_route); res = 1; goto out; } else { if (frametype == ROSE_CLEAR_CONFIRMATION) rose_remove_route(rose_route); goto out; } }
/* * Route a frame to an appropriate AX.25 connection. */ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) { struct rose_neigh *rose_neigh, *new_neigh; struct rose_route *rose_route; struct rose_facilities_struct facilities; rose_address *src_addr, *dest_addr; struct sock *sk; unsigned short frametype; unsigned int lci, new_lci; unsigned char cause, diagnostic; struct device *dev; unsigned long flags; int len; struct sk_buff *skbn; #ifdef CONFIG_FIREWALL if (call_in_firewall(PF_ROSE, skb->dev, skb->data, NULL) != FW_ACCEPT) return 0; #endif frametype = skb->data[2]; lci = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF); src_addr = (rose_address *)(skb->data + 9); dest_addr = (rose_address *)(skb->data + 4); for (rose_neigh = rose_neigh_list; rose_neigh != NULL; rose_neigh = rose_neigh->next) if (ax25cmp(&ax25->dest_addr, &rose_neigh->callsign) == 0 && ax25->device == rose_neigh->dev) break; if (rose_neigh == NULL) { printk("rose_route : unknown neighbour or device %s\n", ax2asc(&ax25->dest_addr)); return 0; } /* * Obviously the link is working, halt the ftimer. */ rose_neigh->ftimer = 0; /* * LCI of zero is always for us, and its always a restart * frame. */ if (lci == 0) { rose_link_rx_restart(skb, rose_neigh, frametype); return 0; } /* * Find an existing socket. */ if ((sk = rose_find_socket(lci, rose_neigh)) != NULL) { if (frametype == ROSE_CALL_REQUEST) { /* F6FBB - Remove an existing unused socket */ rose_clear_queues(sk); sk->protinfo.rose->cause = ROSE_NETWORK_CONGESTION; sk->protinfo.rose->diagnostic = 0; sk->protinfo.rose->neighbour->use--; sk->protinfo.rose->neighbour = NULL; sk->protinfo.rose->state = ROSE_STATE_0; sk->state = TCP_CLOSE; sk->err = 0; sk->shutdown |= SEND_SHUTDOWN; if (!sk->dead) sk->state_change(sk); sk->dead = 1; } else { skb->h.raw = skb->data; return rose_process_rx_frame(sk, skb); } } /* * Is it a Call Request and is it for us ? */ if (frametype == ROSE_CALL_REQUEST) if ((dev = rose_dev_get(dest_addr)) != NULL) { return rose_rx_call_request(skb, dev, rose_neigh, lci); } if (!sysctl_rose_routing_control) { rose_transmit_clear_request(rose_neigh, lci, ROSE_NOT_OBTAINABLE, 0); return 0; } /* * Route it to the next in line if we have an entry for it. */ for (rose_route = rose_route_list; rose_route != NULL; rose_route = rose_route->next) { if (rose_route->tr1.lci == lci && rose_route->tr1.neigh == rose_neigh) { if (frametype == ROSE_CALL_REQUEST) { /* F6FBB - Remove an existing unused route */ rose_remove_route(rose_route); break; } else if (rose_route->tr2.neigh != NULL) { if ((skbn = skb_copy(skb, GFP_ATOMIC)) != NULL) { kfree_skb(skb, FREE_READ); skb = skbn; } skb->data[0] &= 0xF0; skb->data[0] |= (rose_route->tr2.lci >> 8) & 0x0F; skb->data[1] = (rose_route->tr2.lci >> 0) & 0xFF; rose_transmit_link(skb, rose_route->tr2.neigh); if (frametype == ROSE_CLEAR_CONFIRMATION) rose_remove_route(rose_route); return 1; } else { if (frametype == ROSE_CLEAR_CONFIRMATION) rose_remove_route(rose_route); return 0; } } if (rose_route->tr2.lci == lci && rose_route->tr2.neigh == rose_neigh) { if (frametype == ROSE_CALL_REQUEST) { /* F6FBB - Remove an existing unused route */ rose_remove_route(rose_route); break; } else if (rose_route->tr1.neigh != NULL) { if ((skbn = skb_copy(skb, GFP_ATOMIC)) != NULL) { kfree_skb(skb, FREE_READ); skb = skbn; } skb->data[0] &= 0xF0; skb->data[0] |= (rose_route->tr1.lci >> 8) & 0x0F; skb->data[1] = (rose_route->tr1.lci >> 0) & 0xFF; rose_transmit_link(skb, rose_route->tr1.neigh); if (frametype == ROSE_CLEAR_CONFIRMATION) rose_remove_route(rose_route); return 1; } else { if (frametype == ROSE_CLEAR_CONFIRMATION) rose_remove_route(rose_route); return 0; } }