aboutsummaryrefslogtreecommitdiffstats
path: root/net/rose
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /net/rose
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (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.c31
-rw-r--r--net/rose/rose_link.c4
-rw-r--r--net/rose/rose_loopback.c13
-rw-r--r--net/rose/rose_route.c50
-rw-r--r--net/rose/rose_subr.c101
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 }
806rose_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 */
592static struct net_device *rose_ax25_dev_find(char *devname) 592static 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 */
676struct rose_neigh *rose_get_neigh(rose_address *addr, unsigned char *cause, 676struct 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
713out: 718out:
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
358int rose_parse_facilities(unsigned char *p, 396int 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
399static int rose_create_facilities(unsigned char *buffer, struct rose_sock *rose) 436static int rose_create_facilities(unsigned char *buffer, struct rose_sock *rose)