diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /net/rose | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'net/rose')
-rw-r--r-- | net/rose/af_rose.c | 31 | ||||
-rw-r--r-- | net/rose/rose_link.c | 4 | ||||
-rw-r--r-- | net/rose/rose_loopback.c | 13 | ||||
-rw-r--r-- | net/rose/rose_route.c | 50 | ||||
-rw-r--r-- | net/rose/rose_subr.c | 101 |
5 files changed, 119 insertions, 80 deletions
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index d952e7eac188..f9ea925ad9cb 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c | |||
@@ -682,10 +682,8 @@ static int rose_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
682 | if ((unsigned int) addr->srose_ndigis > ROSE_MAX_DIGIS) | 682 | if ((unsigned int) addr->srose_ndigis > ROSE_MAX_DIGIS) |
683 | return -EINVAL; | 683 | return -EINVAL; |
684 | 684 | ||
685 | if ((dev = rose_dev_get(&addr->srose_addr)) == NULL) { | 685 | if ((dev = rose_dev_get(&addr->srose_addr)) == NULL) |
686 | SOCK_DEBUG(sk, "ROSE: bind failed: invalid address\n"); | ||
687 | return -EADDRNOTAVAIL; | 686 | return -EADDRNOTAVAIL; |
688 | } | ||
689 | 687 | ||
690 | source = &addr->srose_call; | 688 | source = &addr->srose_call; |
691 | 689 | ||
@@ -716,7 +714,7 @@ static int rose_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
716 | rose_insert_socket(sk); | 714 | rose_insert_socket(sk); |
717 | 715 | ||
718 | sock_reset_flag(sk, SOCK_ZAPPED); | 716 | sock_reset_flag(sk, SOCK_ZAPPED); |
719 | SOCK_DEBUG(sk, "ROSE: socket is bound\n"); | 717 | |
720 | return 0; | 718 | return 0; |
721 | } | 719 | } |
722 | 720 | ||
@@ -803,7 +801,6 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le | |||
803 | 801 | ||
804 | rose_insert_socket(sk); /* Finish the bind */ | 802 | rose_insert_socket(sk); /* Finish the bind */ |
805 | } | 803 | } |
806 | rose_try_next_neigh: | ||
807 | rose->dest_addr = addr->srose_addr; | 804 | rose->dest_addr = addr->srose_addr; |
808 | rose->dest_call = addr->srose_call; | 805 | rose->dest_call = addr->srose_call; |
809 | rose->rand = ((long)rose & 0xFFFF) + rose->lci; | 806 | rose->rand = ((long)rose & 0xFFFF) + rose->lci; |
@@ -865,12 +862,6 @@ rose_try_next_neigh: | |||
865 | } | 862 | } |
866 | 863 | ||
867 | if (sk->sk_state != TCP_ESTABLISHED) { | 864 | if (sk->sk_state != TCP_ESTABLISHED) { |
868 | /* Try next neighbour */ | ||
869 | rose->neighbour = rose_get_neigh(&addr->srose_addr, &cause, &diagnostic, 0); | ||
870 | if (rose->neighbour) | ||
871 | goto rose_try_next_neigh; | ||
872 | |||
873 | /* No more neighbours */ | ||
874 | sock->state = SS_UNCONNECTED; | 865 | sock->state = SS_UNCONNECTED; |
875 | err = sock_error(sk); /* Always set at this point */ | 866 | err = sock_error(sk); /* Always set at this point */ |
876 | goto out_release; | 867 | goto out_release; |
@@ -985,7 +976,7 @@ int rose_rx_call_request(struct sk_buff *skb, struct net_device *dev, struct ros | |||
985 | struct sock *make; | 976 | struct sock *make; |
986 | struct rose_sock *make_rose; | 977 | struct rose_sock *make_rose; |
987 | struct rose_facilities_struct facilities; | 978 | struct rose_facilities_struct facilities; |
988 | int n, len; | 979 | int n; |
989 | 980 | ||
990 | skb->sk = NULL; /* Initially we don't know who it's for */ | 981 | skb->sk = NULL; /* Initially we don't know who it's for */ |
991 | 982 | ||
@@ -994,9 +985,9 @@ int rose_rx_call_request(struct sk_buff *skb, struct net_device *dev, struct ros | |||
994 | */ | 985 | */ |
995 | memset(&facilities, 0x00, sizeof(struct rose_facilities_struct)); | 986 | memset(&facilities, 0x00, sizeof(struct rose_facilities_struct)); |
996 | 987 | ||
997 | len = (((skb->data[3] >> 4) & 0x0F) + 1) >> 1; | 988 | if (!rose_parse_facilities(skb->data + ROSE_CALL_REQ_FACILITIES_OFF, |
998 | len += (((skb->data[3] >> 0) & 0x0F) + 1) >> 1; | 989 | skb->len - ROSE_CALL_REQ_FACILITIES_OFF, |
999 | if (!rose_parse_facilities(skb->data + len + 4, &facilities)) { | 990 | &facilities)) { |
1000 | rose_transmit_clear_request(neigh, lci, ROSE_INVALID_FACILITY, 76); | 991 | rose_transmit_clear_request(neigh, lci, ROSE_INVALID_FACILITY, 76); |
1001 | return 0; | 992 | return 0; |
1002 | } | 993 | } |
@@ -1116,10 +1107,7 @@ static int rose_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1116 | srose.srose_digis[n] = rose->dest_digis[n]; | 1107 | srose.srose_digis[n] = rose->dest_digis[n]; |
1117 | } | 1108 | } |
1118 | 1109 | ||
1119 | SOCK_DEBUG(sk, "ROSE: sendto: Addresses built.\n"); | ||
1120 | |||
1121 | /* Build a packet */ | 1110 | /* Build a packet */ |
1122 | SOCK_DEBUG(sk, "ROSE: sendto: building packet.\n"); | ||
1123 | /* Sanity check the packet size */ | 1111 | /* Sanity check the packet size */ |
1124 | if (len > 65535) | 1112 | if (len > 65535) |
1125 | return -EMSGSIZE; | 1113 | return -EMSGSIZE; |
@@ -1134,7 +1122,6 @@ static int rose_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1134 | /* | 1122 | /* |
1135 | * Put the data on the end | 1123 | * Put the data on the end |
1136 | */ | 1124 | */ |
1137 | SOCK_DEBUG(sk, "ROSE: Appending user data\n"); | ||
1138 | 1125 | ||
1139 | skb_reset_transport_header(skb); | 1126 | skb_reset_transport_header(skb); |
1140 | skb_put(skb, len); | 1127 | skb_put(skb, len); |
@@ -1159,8 +1146,6 @@ static int rose_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1159 | */ | 1146 | */ |
1160 | asmptr = skb_push(skb, ROSE_MIN_LEN); | 1147 | asmptr = skb_push(skb, ROSE_MIN_LEN); |
1161 | 1148 | ||
1162 | SOCK_DEBUG(sk, "ROSE: Building Network Header.\n"); | ||
1163 | |||
1164 | /* Build a ROSE Network header */ | 1149 | /* Build a ROSE Network header */ |
1165 | asmptr[0] = ((rose->lci >> 8) & 0x0F) | ROSE_GFI; | 1150 | asmptr[0] = ((rose->lci >> 8) & 0x0F) | ROSE_GFI; |
1166 | asmptr[1] = (rose->lci >> 0) & 0xFF; | 1151 | asmptr[1] = (rose->lci >> 0) & 0xFF; |
@@ -1169,10 +1154,6 @@ static int rose_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1169 | if (qbit) | 1154 | if (qbit) |
1170 | asmptr[0] |= ROSE_Q_BIT; | 1155 | asmptr[0] |= ROSE_Q_BIT; |
1171 | 1156 | ||
1172 | SOCK_DEBUG(sk, "ROSE: Built header.\n"); | ||
1173 | |||
1174 | SOCK_DEBUG(sk, "ROSE: Transmitting buffer\n"); | ||
1175 | |||
1176 | if (sk->sk_state != TCP_ESTABLISHED) { | 1157 | if (sk->sk_state != TCP_ESTABLISHED) { |
1177 | kfree_skb(skb); | 1158 | kfree_skb(skb); |
1178 | return -ENOTCONN; | 1159 | return -ENOTCONN; |
diff --git a/net/rose/rose_link.c b/net/rose/rose_link.c index a750a28e0221..fa5f5641a2c2 100644 --- a/net/rose/rose_link.c +++ b/net/rose/rose_link.c | |||
@@ -114,7 +114,7 @@ static int rose_send_frame(struct sk_buff *skb, struct rose_neigh *neigh) | |||
114 | if (ax25s) | 114 | if (ax25s) |
115 | ax25_cb_put(ax25s); | 115 | ax25_cb_put(ax25s); |
116 | 116 | ||
117 | return (neigh->ax25 != NULL); | 117 | return neigh->ax25 != NULL; |
118 | } | 118 | } |
119 | 119 | ||
120 | /* | 120 | /* |
@@ -137,7 +137,7 @@ static int rose_link_up(struct rose_neigh *neigh) | |||
137 | if (ax25s) | 137 | if (ax25s) |
138 | ax25_cb_put(ax25s); | 138 | ax25_cb_put(ax25s); |
139 | 139 | ||
140 | return (neigh->ax25 != NULL); | 140 | return neigh->ax25 != NULL; |
141 | } | 141 | } |
142 | 142 | ||
143 | /* | 143 | /* |
diff --git a/net/rose/rose_loopback.c b/net/rose/rose_loopback.c index ae4a9d99aec7..344456206b70 100644 --- a/net/rose/rose_loopback.c +++ b/net/rose/rose_loopback.c | |||
@@ -73,9 +73,20 @@ static void rose_loopback_timer(unsigned long param) | |||
73 | unsigned int lci_i, lci_o; | 73 | unsigned int lci_i, lci_o; |
74 | 74 | ||
75 | while ((skb = skb_dequeue(&loopback_queue)) != NULL) { | 75 | while ((skb = skb_dequeue(&loopback_queue)) != NULL) { |
76 | if (skb->len < ROSE_MIN_LEN) { | ||
77 | kfree_skb(skb); | ||
78 | continue; | ||
79 | } | ||
76 | lci_i = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF); | 80 | lci_i = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF); |
77 | frametype = skb->data[2]; | 81 | frametype = skb->data[2]; |
78 | dest = (rose_address *)(skb->data + 4); | 82 | if (frametype == ROSE_CALL_REQUEST && |
83 | (skb->len <= ROSE_CALL_REQ_FACILITIES_OFF || | ||
84 | skb->data[ROSE_CALL_REQ_ADDR_LEN_OFF] != | ||
85 | ROSE_CALL_REQ_ADDR_LEN_VAL)) { | ||
86 | kfree_skb(skb); | ||
87 | continue; | ||
88 | } | ||
89 | dest = (rose_address *)(skb->data + ROSE_CALL_REQ_DEST_ADDR_OFF); | ||
79 | lci_o = ROSE_DEFAULT_MAXVC + 1 - lci_i; | 90 | lci_o = ROSE_DEFAULT_MAXVC + 1 - lci_i; |
80 | 91 | ||
81 | skb_reset_transport_header(skb); | 92 | skb_reset_transport_header(skb); |
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 | } |
diff --git a/net/rose/rose_subr.c b/net/rose/rose_subr.c index 1734abba26a2..f6c71caa94b9 100644 --- a/net/rose/rose_subr.c +++ b/net/rose/rose_subr.c | |||
@@ -142,7 +142,7 @@ void rose_write_internal(struct sock *sk, int frametype) | |||
142 | *dptr++ = ROSE_GFI | lci1; | 142 | *dptr++ = ROSE_GFI | lci1; |
143 | *dptr++ = lci2; | 143 | *dptr++ = lci2; |
144 | *dptr++ = frametype; | 144 | *dptr++ = frametype; |
145 | *dptr++ = 0xAA; | 145 | *dptr++ = ROSE_CALL_REQ_ADDR_LEN_VAL; |
146 | memcpy(dptr, &rose->dest_addr, ROSE_ADDR_LEN); | 146 | memcpy(dptr, &rose->dest_addr, ROSE_ADDR_LEN); |
147 | dptr += ROSE_ADDR_LEN; | 147 | dptr += ROSE_ADDR_LEN; |
148 | memcpy(dptr, &rose->source_addr, ROSE_ADDR_LEN); | 148 | memcpy(dptr, &rose->source_addr, ROSE_ADDR_LEN); |
@@ -246,12 +246,16 @@ static int rose_parse_national(unsigned char *p, struct rose_facilities_struct * | |||
246 | do { | 246 | do { |
247 | switch (*p & 0xC0) { | 247 | switch (*p & 0xC0) { |
248 | case 0x00: | 248 | case 0x00: |
249 | if (len < 2) | ||
250 | return -1; | ||
249 | p += 2; | 251 | p += 2; |
250 | n += 2; | 252 | n += 2; |
251 | len -= 2; | 253 | len -= 2; |
252 | break; | 254 | break; |
253 | 255 | ||
254 | case 0x40: | 256 | case 0x40: |
257 | if (len < 3) | ||
258 | return -1; | ||
255 | if (*p == FAC_NATIONAL_RAND) | 259 | if (*p == FAC_NATIONAL_RAND) |
256 | facilities->rand = ((p[1] << 8) & 0xFF00) + ((p[2] << 0) & 0x00FF); | 260 | facilities->rand = ((p[1] << 8) & 0xFF00) + ((p[2] << 0) & 0x00FF); |
257 | p += 3; | 261 | p += 3; |
@@ -260,40 +264,61 @@ static int rose_parse_national(unsigned char *p, struct rose_facilities_struct * | |||
260 | break; | 264 | break; |
261 | 265 | ||
262 | case 0x80: | 266 | case 0x80: |
267 | if (len < 4) | ||
268 | return -1; | ||
263 | p += 4; | 269 | p += 4; |
264 | n += 4; | 270 | n += 4; |
265 | len -= 4; | 271 | len -= 4; |
266 | break; | 272 | break; |
267 | 273 | ||
268 | case 0xC0: | 274 | case 0xC0: |
275 | if (len < 2) | ||
276 | return -1; | ||
269 | l = p[1]; | 277 | l = p[1]; |
278 | if (len < 2 + l) | ||
279 | return -1; | ||
270 | if (*p == FAC_NATIONAL_DEST_DIGI) { | 280 | if (*p == FAC_NATIONAL_DEST_DIGI) { |
271 | if (!fac_national_digis_received) { | 281 | if (!fac_national_digis_received) { |
282 | if (l < AX25_ADDR_LEN) | ||
283 | return -1; | ||
272 | memcpy(&facilities->source_digis[0], p + 2, AX25_ADDR_LEN); | 284 | memcpy(&facilities->source_digis[0], p + 2, AX25_ADDR_LEN); |
273 | facilities->source_ndigis = 1; | 285 | facilities->source_ndigis = 1; |
274 | } | 286 | } |
275 | } | 287 | } |
276 | else if (*p == FAC_NATIONAL_SRC_DIGI) { | 288 | else if (*p == FAC_NATIONAL_SRC_DIGI) { |
277 | if (!fac_national_digis_received) { | 289 | if (!fac_national_digis_received) { |
290 | if (l < AX25_ADDR_LEN) | ||
291 | return -1; | ||
278 | memcpy(&facilities->dest_digis[0], p + 2, AX25_ADDR_LEN); | 292 | memcpy(&facilities->dest_digis[0], p + 2, AX25_ADDR_LEN); |
279 | facilities->dest_ndigis = 1; | 293 | facilities->dest_ndigis = 1; |
280 | } | 294 | } |
281 | } | 295 | } |
282 | else if (*p == FAC_NATIONAL_FAIL_CALL) { | 296 | else if (*p == FAC_NATIONAL_FAIL_CALL) { |
297 | if (l < AX25_ADDR_LEN) | ||
298 | return -1; | ||
283 | memcpy(&facilities->fail_call, p + 2, AX25_ADDR_LEN); | 299 | memcpy(&facilities->fail_call, p + 2, AX25_ADDR_LEN); |
284 | } | 300 | } |
285 | else if (*p == FAC_NATIONAL_FAIL_ADD) { | 301 | else if (*p == FAC_NATIONAL_FAIL_ADD) { |
302 | if (l < 1 + ROSE_ADDR_LEN) | ||
303 | return -1; | ||
286 | memcpy(&facilities->fail_addr, p + 3, ROSE_ADDR_LEN); | 304 | memcpy(&facilities->fail_addr, p + 3, ROSE_ADDR_LEN); |
287 | } | 305 | } |
288 | else if (*p == FAC_NATIONAL_DIGIS) { | 306 | else if (*p == FAC_NATIONAL_DIGIS) { |
307 | if (l % AX25_ADDR_LEN) | ||
308 | return -1; | ||
289 | fac_national_digis_received = 1; | 309 | fac_national_digis_received = 1; |
290 | facilities->source_ndigis = 0; | 310 | facilities->source_ndigis = 0; |
291 | facilities->dest_ndigis = 0; | 311 | facilities->dest_ndigis = 0; |
292 | for (pt = p + 2, lg = 0 ; lg < l ; pt += AX25_ADDR_LEN, lg += AX25_ADDR_LEN) { | 312 | for (pt = p + 2, lg = 0 ; lg < l ; pt += AX25_ADDR_LEN, lg += AX25_ADDR_LEN) { |
293 | if (pt[6] & AX25_HBIT) | 313 | if (pt[6] & AX25_HBIT) { |
314 | if (facilities->dest_ndigis >= ROSE_MAX_DIGIS) | ||
315 | return -1; | ||
294 | memcpy(&facilities->dest_digis[facilities->dest_ndigis++], pt, AX25_ADDR_LEN); | 316 | memcpy(&facilities->dest_digis[facilities->dest_ndigis++], pt, AX25_ADDR_LEN); |
295 | else | 317 | } else { |
318 | if (facilities->source_ndigis >= ROSE_MAX_DIGIS) | ||
319 | return -1; | ||
296 | memcpy(&facilities->source_digis[facilities->source_ndigis++], pt, AX25_ADDR_LEN); | 320 | memcpy(&facilities->source_digis[facilities->source_ndigis++], pt, AX25_ADDR_LEN); |
321 | } | ||
297 | } | 322 | } |
298 | } | 323 | } |
299 | p += l + 2; | 324 | p += l + 2; |
@@ -314,25 +339,38 @@ static int rose_parse_ccitt(unsigned char *p, struct rose_facilities_struct *fac | |||
314 | do { | 339 | do { |
315 | switch (*p & 0xC0) { | 340 | switch (*p & 0xC0) { |
316 | case 0x00: | 341 | case 0x00: |
342 | if (len < 2) | ||
343 | return -1; | ||
317 | p += 2; | 344 | p += 2; |
318 | n += 2; | 345 | n += 2; |
319 | len -= 2; | 346 | len -= 2; |
320 | break; | 347 | break; |
321 | 348 | ||
322 | case 0x40: | 349 | case 0x40: |
350 | if (len < 3) | ||
351 | return -1; | ||
323 | p += 3; | 352 | p += 3; |
324 | n += 3; | 353 | n += 3; |
325 | len -= 3; | 354 | len -= 3; |
326 | break; | 355 | break; |
327 | 356 | ||
328 | case 0x80: | 357 | case 0x80: |
358 | if (len < 4) | ||
359 | return -1; | ||
329 | p += 4; | 360 | p += 4; |
330 | n += 4; | 361 | n += 4; |
331 | len -= 4; | 362 | len -= 4; |
332 | break; | 363 | break; |
333 | 364 | ||
334 | case 0xC0: | 365 | case 0xC0: |
366 | if (len < 2) | ||
367 | return -1; | ||
335 | l = p[1]; | 368 | l = p[1]; |
369 | |||
370 | /* Prevent overflows*/ | ||
371 | if (l < 10 || l > 20) | ||
372 | return -1; | ||
373 | |||
336 | if (*p == FAC_CCITT_DEST_NSAP) { | 374 | if (*p == FAC_CCITT_DEST_NSAP) { |
337 | memcpy(&facilities->source_addr, p + 7, ROSE_ADDR_LEN); | 375 | memcpy(&facilities->source_addr, p + 7, ROSE_ADDR_LEN); |
338 | memcpy(callsign, p + 12, l - 10); | 376 | memcpy(callsign, p + 12, l - 10); |
@@ -355,45 +393,44 @@ static int rose_parse_ccitt(unsigned char *p, struct rose_facilities_struct *fac | |||
355 | return n; | 393 | return n; |
356 | } | 394 | } |
357 | 395 | ||
358 | int rose_parse_facilities(unsigned char *p, | 396 | int rose_parse_facilities(unsigned char *p, unsigned packet_len, |
359 | struct rose_facilities_struct *facilities) | 397 | struct rose_facilities_struct *facilities) |
360 | { | 398 | { |
361 | int facilities_len, len; | 399 | int facilities_len, len; |
362 | 400 | ||
363 | facilities_len = *p++; | 401 | facilities_len = *p++; |
364 | 402 | ||
365 | if (facilities_len == 0) | 403 | if (facilities_len == 0 || (unsigned)facilities_len > packet_len) |
366 | return 0; | 404 | return 0; |
367 | 405 | ||
368 | while (facilities_len > 0) { | 406 | while (facilities_len >= 3 && *p == 0x00) { |
369 | if (*p == 0x00) { | 407 | facilities_len--; |
370 | facilities_len--; | 408 | p++; |
371 | p++; | 409 | |
372 | 410 | switch (*p) { | |
373 | switch (*p) { | 411 | case FAC_NATIONAL: /* National */ |
374 | case FAC_NATIONAL: /* National */ | 412 | len = rose_parse_national(p + 1, facilities, facilities_len - 1); |
375 | len = rose_parse_national(p + 1, facilities, facilities_len - 1); | 413 | break; |
376 | facilities_len -= len + 1; | 414 | |
377 | p += len + 1; | 415 | case FAC_CCITT: /* CCITT */ |
378 | break; | 416 | len = rose_parse_ccitt(p + 1, facilities, facilities_len - 1); |
379 | 417 | break; | |
380 | case FAC_CCITT: /* CCITT */ | 418 | |
381 | len = rose_parse_ccitt(p + 1, facilities, facilities_len - 1); | 419 | default: |
382 | facilities_len -= len + 1; | 420 | printk(KERN_DEBUG "ROSE: rose_parse_facilities - unknown facilities family %02X\n", *p); |
383 | p += len + 1; | 421 | len = 1; |
384 | break; | 422 | break; |
385 | 423 | } | |
386 | default: | 424 | |
387 | printk(KERN_DEBUG "ROSE: rose_parse_facilities - unknown facilities family %02X\n", *p); | 425 | if (len < 0) |
388 | facilities_len--; | 426 | return 0; |
389 | p++; | 427 | if (WARN_ON(len >= facilities_len)) |
390 | break; | 428 | return 0; |
391 | } | 429 | facilities_len -= len + 1; |
392 | } else | 430 | p += len + 1; |
393 | break; /* Error in facilities format */ | ||
394 | } | 431 | } |
395 | 432 | ||
396 | return 1; | 433 | return facilities_len == 0; |
397 | } | 434 | } |
398 | 435 | ||
399 | static int rose_create_facilities(unsigned char *buffer, struct rose_sock *rose) | 436 | static int rose_create_facilities(unsigned char *buffer, struct rose_sock *rose) |