diff options
Diffstat (limited to 'net/rose/rose_route.c')
-rw-r--r-- | net/rose/rose_route.c | 50 |
1 files changed, 30 insertions, 20 deletions
diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c index b4fdaac233f7..479cae57d187 100644 --- a/net/rose/rose_route.c +++ b/net/rose/rose_route.c | |||
@@ -587,7 +587,7 @@ static int rose_clear_routes(void) | |||
587 | 587 | ||
588 | /* | 588 | /* |
589 | * Check that the device given is a valid AX.25 interface that is "up". | 589 | * Check that the device given is a valid AX.25 interface that is "up". |
590 | * called whith RTNL | 590 | * called with RTNL |
591 | */ | 591 | */ |
592 | static struct net_device *rose_ax25_dev_find(char *devname) | 592 | static struct net_device *rose_ax25_dev_find(char *devname) |
593 | { | 593 | { |
@@ -674,29 +674,34 @@ struct rose_route *rose_route_free_lci(unsigned int lci, struct rose_neigh *neig | |||
674 | * Find a neighbour or a route given a ROSE address. | 674 | * Find a neighbour or a route given a ROSE address. |
675 | */ | 675 | */ |
676 | struct rose_neigh *rose_get_neigh(rose_address *addr, unsigned char *cause, | 676 | struct rose_neigh *rose_get_neigh(rose_address *addr, unsigned char *cause, |
677 | unsigned char *diagnostic, int new) | 677 | unsigned char *diagnostic, int route_frame) |
678 | { | 678 | { |
679 | struct rose_neigh *res = NULL; | 679 | struct rose_neigh *res = NULL; |
680 | struct rose_node *node; | 680 | struct rose_node *node; |
681 | int failed = 0; | 681 | int failed = 0; |
682 | int i; | 682 | int i; |
683 | 683 | ||
684 | if (!new) spin_lock_bh(&rose_node_list_lock); | 684 | if (!route_frame) spin_lock_bh(&rose_node_list_lock); |
685 | for (node = rose_node_list; node != NULL; node = node->next) { | 685 | for (node = rose_node_list; node != NULL; node = node->next) { |
686 | if (rosecmpm(addr, &node->address, node->mask) == 0) { | 686 | if (rosecmpm(addr, &node->address, node->mask) == 0) { |
687 | for (i = 0; i < node->count; i++) { | 687 | for (i = 0; i < node->count; i++) { |
688 | if (new) { | 688 | if (node->neighbour[i]->restarted) { |
689 | if (node->neighbour[i]->restarted) { | 689 | res = node->neighbour[i]; |
690 | res = node->neighbour[i]; | 690 | goto out; |
691 | goto out; | ||
692 | } | ||
693 | } | 691 | } |
694 | else { | 692 | } |
693 | } | ||
694 | } | ||
695 | if (!route_frame) { /* connect request */ | ||
696 | for (node = rose_node_list; node != NULL; node = node->next) { | ||
697 | if (rosecmpm(addr, &node->address, node->mask) == 0) { | ||
698 | for (i = 0; i < node->count; i++) { | ||
695 | if (!rose_ftimer_running(node->neighbour[i])) { | 699 | if (!rose_ftimer_running(node->neighbour[i])) { |
696 | res = node->neighbour[i]; | 700 | res = node->neighbour[i]; |
701 | failed = 0; | ||
697 | goto out; | 702 | goto out; |
698 | } else | 703 | } |
699 | failed = 1; | 704 | failed = 1; |
700 | } | 705 | } |
701 | } | 706 | } |
702 | } | 707 | } |
@@ -711,8 +716,7 @@ struct rose_neigh *rose_get_neigh(rose_address *addr, unsigned char *cause, | |||
711 | } | 716 | } |
712 | 717 | ||
713 | out: | 718 | out: |
714 | if (!new) spin_unlock_bh(&rose_node_list_lock); | 719 | if (!route_frame) spin_unlock_bh(&rose_node_list_lock); |
715 | |||
716 | return res; | 720 | return res; |
717 | } | 721 | } |
718 | 722 | ||
@@ -857,7 +861,7 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) | |||
857 | unsigned int lci, new_lci; | 861 | unsigned int lci, new_lci; |
858 | unsigned char cause, diagnostic; | 862 | unsigned char cause, diagnostic; |
859 | struct net_device *dev; | 863 | struct net_device *dev; |
860 | int len, res = 0; | 864 | int res = 0; |
861 | char buf[11]; | 865 | char buf[11]; |
862 | 866 | ||
863 | #if 0 | 867 | #if 0 |
@@ -865,10 +869,17 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) | |||
865 | return res; | 869 | return res; |
866 | #endif | 870 | #endif |
867 | 871 | ||
872 | if (skb->len < ROSE_MIN_LEN) | ||
873 | return res; | ||
868 | frametype = skb->data[2]; | 874 | frametype = skb->data[2]; |
869 | lci = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF); | 875 | lci = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF); |
870 | src_addr = (rose_address *)(skb->data + 9); | 876 | if (frametype == ROSE_CALL_REQUEST && |
871 | dest_addr = (rose_address *)(skb->data + 4); | 877 | (skb->len <= ROSE_CALL_REQ_FACILITIES_OFF || |
878 | skb->data[ROSE_CALL_REQ_ADDR_LEN_OFF] != | ||
879 | ROSE_CALL_REQ_ADDR_LEN_VAL)) | ||
880 | return res; | ||
881 | src_addr = (rose_address *)(skb->data + ROSE_CALL_REQ_SRC_ADDR_OFF); | ||
882 | dest_addr = (rose_address *)(skb->data + ROSE_CALL_REQ_DEST_ADDR_OFF); | ||
872 | 883 | ||
873 | spin_lock_bh(&rose_neigh_list_lock); | 884 | spin_lock_bh(&rose_neigh_list_lock); |
874 | spin_lock_bh(&rose_route_list_lock); | 885 | spin_lock_bh(&rose_route_list_lock); |
@@ -1006,12 +1017,11 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) | |||
1006 | goto out; | 1017 | goto out; |
1007 | } | 1018 | } |
1008 | 1019 | ||
1009 | len = (((skb->data[3] >> 4) & 0x0F) + 1) >> 1; | ||
1010 | len += (((skb->data[3] >> 0) & 0x0F) + 1) >> 1; | ||
1011 | |||
1012 | memset(&facilities, 0x00, sizeof(struct rose_facilities_struct)); | 1020 | memset(&facilities, 0x00, sizeof(struct rose_facilities_struct)); |
1013 | 1021 | ||
1014 | if (!rose_parse_facilities(skb->data + len + 4, &facilities)) { | 1022 | if (!rose_parse_facilities(skb->data + ROSE_CALL_REQ_FACILITIES_OFF, |
1023 | skb->len - ROSE_CALL_REQ_FACILITIES_OFF, | ||
1024 | &facilities)) { | ||
1015 | rose_transmit_clear_request(rose_neigh, lci, ROSE_INVALID_FACILITY, 76); | 1025 | rose_transmit_clear_request(rose_neigh, lci, ROSE_INVALID_FACILITY, 76); |
1016 | goto out; | 1026 | goto out; |
1017 | } | 1027 | } |