diff options
Diffstat (limited to 'net/x25/x25_facilities.c')
| -rw-r--r-- | net/x25/x25_facilities.c | 60 | 
1 files changed, 39 insertions, 21 deletions
diff --git a/net/x25/x25_facilities.c b/net/x25/x25_facilities.c index 55187c8f642..7ecd04c2136 100644 --- a/net/x25/x25_facilities.c +++ b/net/x25/x25_facilities.c @@ -21,20 +21,32 @@   *					on response.   */ +#define pr_fmt(fmt) "X25: " fmt +  #include <linux/kernel.h>  #include <linux/string.h>  #include <linux/skbuff.h>  #include <net/sock.h>  #include <net/x25.h> -/* - * Parse a set of facilities into the facilities structures. Unrecognised - *	facilities are written to the debug log file. +/** + * x25_parse_facilities - Parse facilities from skb into the facilities structs + * + * @skb: sk_buff to parse + * @facilities: Regular facilities, updated as facilities are found + * @dte_facs: ITU DTE facilities, updated as DTE facilities are found + * @vc_fac_mask: mask is updated with all facilities found + * + * Return codes: + *  -1 - Parsing error, caller should drop call and clean up + *   0 - Parse OK, this skb has no facilities + *  >0 - Parse OK, returns the length of the facilities header + *   */  int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities,  		struct x25_dte_facilities *dte_facs, unsigned long *vc_fac_mask)  { -	unsigned char *p = skb->data; +	unsigned char *p;  	unsigned int len;  	*vc_fac_mask = 0; @@ -50,19 +62,21 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities,  	memset(dte_facs->called_ae, '\0', sizeof(dte_facs->called_ae));  	memset(dte_facs->calling_ae, '\0', sizeof(dte_facs->calling_ae)); -	if (skb->len < 1) +	if (!pskb_may_pull(skb, 1))  		return 0; -	len = *p++; +	len = skb->data[0]; -	if (len >= skb->len) +	if (!pskb_may_pull(skb, 1 + len))  		return -1; +	p = skb->data + 1; +  	while (len > 0) {  		switch (*p & X25_FAC_CLASS_MASK) {  		case X25_FAC_CLASS_A:  			if (len < 2) -				return 0; +				return -1;  			switch (*p) {  			case X25_FAC_REVERSE:  				if((p[1] & 0x81) == 0x81) { @@ -97,7 +111,7 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities,  			case X25_MARKER:  				break;  			default: -				printk(KERN_DEBUG "X.25: unknown facility " +				pr_debug("unknown facility "  				       "%02X, value %02X\n",  				       p[0], p[1]);  				break; @@ -107,7 +121,7 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities,  			break;  		case X25_FAC_CLASS_B:  			if (len < 3) -				return 0; +				return -1;  			switch (*p) {  			case X25_FAC_PACKET_SIZE:  				facilities->pacsize_in  = p[1]; @@ -120,7 +134,7 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities,  				*vc_fac_mask |= X25_MASK_WINDOW_SIZE;  				break;  			default: -				printk(KERN_DEBUG "X.25: unknown facility " +				pr_debug("unknown facility "  				       "%02X, values %02X, %02X\n",  				       p[0], p[1], p[2]);  				break; @@ -130,8 +144,8 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities,  			break;  		case X25_FAC_CLASS_C:  			if (len < 4) -				return 0; -			printk(KERN_DEBUG "X.25: unknown facility %02X, " +				return -1; +			pr_debug("unknown facility %02X, "  			       "values %02X, %02X, %02X\n",  			       p[0], p[1], p[2], p[3]);  			p   += 4; @@ -139,24 +153,28 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities,  			break;  		case X25_FAC_CLASS_D:  			if (len < p[1] + 2) -				return 0; +				return -1;  			switch (*p) {  			case X25_FAC_CALLING_AE:  				if (p[1] > X25_MAX_DTE_FACIL_LEN || p[1] <= 1) -					return 0; +					return -1; +				if (p[2] > X25_MAX_AE_LEN) +					return -1;  				dte_facs->calling_len = p[2];  				memcpy(dte_facs->calling_ae, &p[3], p[1] - 1);  				*vc_fac_mask |= X25_MASK_CALLING_AE;  				break;  			case X25_FAC_CALLED_AE:  				if (p[1] > X25_MAX_DTE_FACIL_LEN || p[1] <= 1) -					return 0; +					return -1; +				if (p[2] > X25_MAX_AE_LEN) +					return -1;  				dte_facs->called_len = p[2];  				memcpy(dte_facs->called_ae, &p[3], p[1] - 1);  				*vc_fac_mask |= X25_MASK_CALLED_AE;  				break;  			default: -				printk(KERN_DEBUG "X.25: unknown facility %02X," +				pr_debug("unknown facility %02X,"  					"length %d\n", p[0], p[1]);  				break;  			} @@ -219,7 +237,7 @@ int x25_create_facilities(unsigned char *buffer,  	}  	if (dte_facs->calling_len && (facil_mask & X25_MASK_CALLING_AE)) { -		unsigned bytecount = (dte_facs->calling_len + 1) >> 1; +		unsigned int bytecount = (dte_facs->calling_len + 1) >> 1;  		*p++ = X25_FAC_CALLING_AE;  		*p++ = 1 + bytecount;  		*p++ = dte_facs->calling_len; @@ -228,7 +246,7 @@ int x25_create_facilities(unsigned char *buffer,  	}  	if (dte_facs->called_len && (facil_mask & X25_MASK_CALLED_AE)) { -		unsigned bytecount = (dte_facs->called_len % 2) ? +		unsigned int bytecount = (dte_facs->called_len % 2) ?  		dte_facs->called_len / 2 + 1 :  		dte_facs->called_len / 2;  		*p++ = X25_FAC_CALLED_AE; @@ -325,12 +343,12 @@ void x25_limit_facilities(struct x25_facilities *facilities,  	if (!nb->extended) {  		if (facilities->winsize_in  > 7) { -			printk(KERN_DEBUG "X.25: incoming winsize limited to 7\n"); +			pr_debug("incoming winsize limited to 7\n");  			facilities->winsize_in = 7;  		}  		if (facilities->winsize_out > 7) {  			facilities->winsize_out = 7; -			printk( KERN_DEBUG "X.25: outgoing winsize limited to 7\n"); +			pr_debug("outgoing winsize limited to 7\n");  		}  	}  }  | 
