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) {
- fput(job->udp_sock->file);
- fput(job->can_sock->file);
- 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)