type = cpu_to_be16(type);
vec[0].iov_base = &type;
+ vec[0].iov_len = sizeof(type);
vec[1].iov_base = cf;
vec[1].iov_len = sizeof(*cf);
- err = kernel_sendmsg(udp_sock, &mh, vec, 2, sizeof(*cf));
+ err = kernel_sendmsg(udp_sock, &mh, vec, 2, sizeof(type)+sizeof(*cf));
return err;
}
vec[1].iov_base = &cf;
vec[1].iov_len = sizeof(cf);
ret = kernel_recvmsg(udp_sock, &mh, vec, 2,
- sizeof(cf), 0);
+ sizeof(type) + sizeof(cf), 0);
if (ret != sizeof(type) + sizeof(cf))
break;
err = copy_from_user(&job->udp_dst, (void __user *)(arg + sizeof(struct cegw_ioctl)), dstcnt*addrlen);
if (err != 0) {
- kfree(job);
- return -EFAULT;
+ err = -EFAULT;
+ goto err_free;
}
for (i=0; i<dstcnt; i++) {
if (job->udp_dst[i].sin_family != AF_INET) {
- kfree(job);
- return -EAFNOSUPPORT;
+ err = -EAFNOSUPPORT;
+ goto err_free;
}
}
job->udp_sock = sockfd_lookup(gwctl.udp_sock, &err);
- if (job->udp_sock == NULL) {
- kfree(job);
- return err;
- }
+ if (job->udp_sock == NULL)
+ goto err_free;
job->can_sock = sockfd_lookup(gwctl.can_sock, &err);
- if (job->can_sock == NULL) {
- fput(job->udp_sock->file);
- kfree(job);
- return err;
- }
+ if (job->can_sock == NULL)
+ goto err_put_udp;
if (job->can_sock->ops->family != AF_CAN ||
job->can_sock->type != SOCK_RAW) {
- kfree(job);
- return -EBADF;
+ err = -EBADF;
+ goto err_put_all;
}
job->udp_dstcnt = dstcnt;
err = cegw_thread_start(job);
if (err != 0)
- return err;
+ return err; /* cegw_thread_start performs cleaup for us. */
file->private_data = job;
return 0;
+
+err_put_all:
+ fput(job->can_sock->file);
+err_put_udp:
+ fput(job->udp_sock->file);
+err_free:
+ kfree(job);
+ return err;
}
static long cegw_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
static int __init cegw_init(void)
{
- printk(KERN_INFO "can: can-eth gateway\n");
+ pr_info("can: can-eth gateway\n");
return misc_register(&cegw_device);
}