|
@@ -422,48 +422,20 @@ error:
|
|
|
|
|
|
static int raw_probe_proto_opt(struct flowi4 *fl4, struct msghdr *msg)
|
|
|
{
|
|
|
- struct iovec *iov;
|
|
|
- u8 __user *type = NULL;
|
|
|
- u8 __user *code = NULL;
|
|
|
- int probed = 0;
|
|
|
- unsigned int i;
|
|
|
+ struct icmphdr icmph;
|
|
|
+ int err;
|
|
|
|
|
|
- if (!msg->msg_iov)
|
|
|
+ if (fl4->flowi4_proto != IPPROTO_ICMP)
|
|
|
return 0;
|
|
|
|
|
|
- for (i = 0; i < msg->msg_iovlen; i++) {
|
|
|
- iov = &msg->msg_iov[i];
|
|
|
- if (!iov)
|
|
|
- continue;
|
|
|
-
|
|
|
- switch (fl4->flowi4_proto) {
|
|
|
- case IPPROTO_ICMP:
|
|
|
- /* check if one-byte field is readable or not. */
|
|
|
- if (iov->iov_base && iov->iov_len < 1)
|
|
|
- break;
|
|
|
-
|
|
|
- if (!type) {
|
|
|
- type = iov->iov_base;
|
|
|
- /* check if code field is readable or not. */
|
|
|
- if (iov->iov_len > 1)
|
|
|
- code = type + 1;
|
|
|
- } else if (!code)
|
|
|
- code = iov->iov_base;
|
|
|
-
|
|
|
- if (type && code) {
|
|
|
- if (get_user(fl4->fl4_icmp_type, type) ||
|
|
|
- get_user(fl4->fl4_icmp_code, code))
|
|
|
- return -EFAULT;
|
|
|
- probed = 1;
|
|
|
- }
|
|
|
- break;
|
|
|
- default:
|
|
|
- probed = 1;
|
|
|
- break;
|
|
|
- }
|
|
|
- if (probed)
|
|
|
- break;
|
|
|
- }
|
|
|
+ /* We only need the first two bytes. */
|
|
|
+ err = memcpy_fromiovecend((void *)&icmph, msg->msg_iov, 0, 2);
|
|
|
+ if (err)
|
|
|
+ return err;
|
|
|
+
|
|
|
+ fl4->fl4_icmp_type = icmph.type;
|
|
|
+ fl4->fl4_icmp_code = icmph.code;
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|