Beispiel #1
0
struct sock *
netlink_kernel_create(int unit, void (*input)(struct sock *sk, int len))
{
	struct socket *sock;
	struct sock *sk;

	if (unit<0 || unit>=MAX_LINKS)
		return NULL;

	if (!(sock = sock_alloc())) 
		return NULL;

	sock->type = SOCK_RAW;

	if (netlink_create(sock, unit) < 0) {
		sock_release(sock);
		return NULL;
	}
	sk = sock->sk;
	sk->data_ready = netlink_data_ready;
	if (input)
		sk->protinfo.af_netlink->data_ready = input;

	netlink_insert(sk, 0);
	return sk;
}
Beispiel #2
0
int __init igmp6_init(struct net_proto_family *ops)
{
	struct sock *sk;
	int err;

	igmp6_socket = sock_alloc();
	if (igmp6_socket == NULL) {
		MDBG1((KERN_ERR
		       "Failed to create the IGMP6 control socket.\n"));
		return -1;
	}
	igmp6_socket->inode->i_uid = 0;
	igmp6_socket->inode->i_gid = 0;
	igmp6_socket->type = SOCK_RAW;

	if((err = ops->create(igmp6_socket, IPPROTO_ICMPV6)) < 0) {
		MDBG1((KERN_ERR
		       "Failed to initialize the IGMP6 control socket (err %d).\n",
		       err));
		sock_release(igmp6_socket);
		igmp6_socket = NULL; /* For safety. */
		return err;
	}

	sk = igmp6_socket->sk;
	sk->allocation = GFP_ATOMIC;
	sk->prot->unhash(sk);

	sk->net_pinfo.af_inet6.hop_limit = 1;
#ifdef CONFIG_PROC_FS
	create_proc_read_entry("net/igmp6", 0, 0, igmp6_read_proc, NULL);
#endif

	return 0;
}
Beispiel #3
0
/* 创建一个socket的套接字,一般会根据type的类型来确定protocol的类型,
 * protocol的类型一般默认为IPPROTO_IP
 */
static int sock_socket(int family, int type, int protocol)
{
  int i, fd;
  struct socket *sock;
  struct proto_ops *ops;

  DPRINTF((net_debug,
	"NET: sock_socket: family = %d, type = %d, protocol = %d\n",
						family, type, protocol));

  /* Locate the correct protocol family. */
  /* 找到协议族的操作函数 */
  for (i = 0; i < NPROTO; ++i) {
	if (pops[i] == NULL) continue;
	if (pops[i]->family == family) break;
  }
  if (i == NPROTO) {
	DPRINTF((net_debug, "NET: sock_socket: family not found\n"));
	return(-EINVAL);
  }
  ops = pops[i];

  /*
   * Check that this is a type that we know how to manipulate and
   * the protocol makes sense here. The family can still reject the
   * protocol later.
   */
  if ((type != SOCK_STREAM && type != SOCK_DGRAM &&
       type != SOCK_SEQPACKET && type != SOCK_RAW &&
       type != SOCK_PACKET) || protocol < 0)
							return(-EINVAL);

  /*
   * allocate the socket and allow the family to set things up. if
   * the protocol is 0, the family is instructed to select an appropriate
   * default.
   */
  if (!(sock = sock_alloc(1))) {
	printk("sock_socket: no more sockets\n");
	return(-EAGAIN);
  }
  sock->type = type;
  sock->ops = ops;
  /* 根据不同的协议族函数集来创建socket,
    * 因此在不同协议的proto_ops结构当中是没有socket调用的, 
    * 只有create函数 
    */
  if ((i = sock->ops->create(sock, protocol)) < 0) {
	sock_release(sock);
	return(i);
  }

  if ((fd = get_fd(SOCK_INODE(sock))) < 0) {
	sock_release(sock);
	return(-EINVAL);
  }

  return(fd);
}
Beispiel #4
0
/*
 * perform the socket system call. we locate the appropriate family, then
 * create a fresh socket.
 */
static int
sock_socket(int family, int type, int protocol)
{
	int i, fd;
	struct socket *sock;
	struct proto_ops *ops;

	PRINTK("sys_socket: family = %d (%s), type = %d, protocol = %d\n",
	       family, family_name(family), type, protocol);

	/*
	 * locate the correct protocol family
	 */
	for (i = 0; i < NPROTO; ++i)
		if (proto_table[i].family == family)
			break;
	if (i == NPROTO) {
		PRINTK("sys_socket: family not found\n");
		return -EINVAL;
	}
	ops = proto_table[i].ops;

	/*
	 * check that this is a type that we know how to manipulate and
	 * the protocol makes sense here. the family can still reject the
	 * protocol later.
	 */
	if ((type != SOCK_STREAM &&
	     type != SOCK_DGRAM &&
	     type != SOCK_SEQPACKET &&
	     type != SOCK_RAW) ||
	    protocol < 0)
		return -EINVAL;

	/*
	 * allocate the socket and allow the family to set things up. if
	 * the protocol is 0, the family is instructed to select an appropriate
	 * default.
	 */
	if (!(sock = sock_alloc(1))) {
		printk("sys_socket: no more sockets\n");
		return -EAGAIN;
	}
	sock->type = type;
	sock->ops = ops;
	if ((i = sock->ops->create(sock, protocol)) < 0) {
		sock_release(sock);
		return i;
	}

	if ((fd = get_fd(SOCK_INODE(sock))) < 0) {
		sock_release(sock);
		return -EINVAL;
	}

	return fd;
}
Beispiel #5
0
/* fd是监听的套接字,该函数的执行过程为,首先在sockets数组当中申请一个
 * struct socket,在申请struct socket的过程中就给socket分配了inode节点,
 * 然后在分配一个struct file结构,最后就返回一个新的文件描述符,该过程是一个
 * 反向的过程
 */
static int sock_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_addrlen)
{
  struct file *file;
  struct socket *sock, *newsock;
  int i;

  DPRINTF((net_debug, "NET: sock_accept: fd = %d\n", fd));
  if (fd < 0 || fd >= NR_OPEN || ((file = current->filp[fd]) == NULL))
								return(-EBADF);

  /* 找到监听fd的socket结构 */
  if (!(sock = sockfd_lookup(fd, &file))) return(-ENOTSOCK);
  if (sock->state != SS_UNCONNECTED) {
	DPRINTF((net_debug, "NET: sock_accept: socket isn't unconnected\n"));
	return(-EINVAL);
  }
  if (!(sock->flags & SO_ACCEPTCON)) {
	DPRINTF((net_debug,
		"NET: sock_accept: socket not accepting connections!\n"));
	return(-EINVAL);
  }

	/* 非阻塞的获取一个socket结构 */
  if (!(newsock = sock_alloc(0))) {
	printk("NET: sock_accept: no more sockets\n");
	return(-EAGAIN);
  }
  /* 两个socket的类型,协议族操作函数相同 */
  newsock->type = sock->type;
  newsock->ops = sock->ops;
  if ((i = sock->ops->dup(newsock, sock)) < 0) {
	sock_release(newsock);
	return(i);
  }

  i = newsock->ops->accept(sock, newsock, file->f_flags);
  if ( i < 0) {
	sock_release(newsock);
	return(i);
  }

  /* 给新的socket分配一个文件描述符 */
  if ((fd = get_fd(SOCK_INODE(newsock))) < 0) {
	sock_release(newsock);
	return(-EINVAL);
  }

  DPRINTF((net_debug, "NET: sock_accept: connected socket 0x%x via 0x%x\n",
							sock, newsock));

  if (upeer_sockaddr)
	newsock->ops->getname(newsock, upeer_sockaddr, upeer_addrlen, 1);

  /* 返回新的socket文件描述符 */
  return(fd);
}
Beispiel #6
0
struct sock *sock_create(int family, int type, int protocol) {
	int ret;
	struct sock *new_sk;
	const struct net_family *nfamily;
	const struct net_family_type *nftype;
	const struct net_sock *nsock;

	nfamily = net_family_lookup(family);
	if (nfamily == NULL) {
		return err_ptr(EAFNOSUPPORT);
	}

	nftype = net_family_type_lookup(nfamily, type);
	if (nftype == NULL) {
		return err_ptr(EPROTOTYPE);
	}

	nsock = net_sock_lookup(family, type, protocol);
	if (nsock == NULL) {
		return err_ptr(EPROTONOSUPPORT);
	}

	new_sk = sock_alloc(nftype->ops, nsock->ops);
	if (new_sk == NULL) {
		return err_ptr(ENOMEM);
	}

	sock_init(new_sk, family, type, nsock->protocol,
			nftype->ops, nsock->ops,
			nfamily->out_ops != NULL ? *nfamily->out_ops : NULL);

	assert(new_sk->f_ops != NULL);
	ret = new_sk->f_ops->init(new_sk);
	if (ret != 0) {
		sock_release(new_sk);
		return err_ptr(-ret);
	}

	assert(new_sk->p_ops != NULL);
	if (new_sk->p_ops->init != NULL) {
		ret = new_sk->p_ops->init(new_sk);
		if (ret != 0) {
			sock_close(new_sk);
			return err_ptr(-ret);
		}
	}

	sock_hash(new_sk);


	return new_sk;
}
Beispiel #7
0
/*
 * for accept, we attempt to create a new socket, set up the link with the
 * client, wake up the client, then return the new connected fd.
 */
static int
sock_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_addrlen)
{
	struct file *file;
	struct socket *sock, *newsock;
	int i;

	PRINTK("sys_accept: fd = %d\n", fd);
	if (!(sock = sockfd_lookup(fd, &file)))
		return -EBADF;
	if (sock->state != SS_UNCONNECTED) {
		PRINTK("sys_accept: socket isn't unconnected\n");
		return -EINVAL;
	}
	if (!(sock->flags & SO_ACCEPTCON)) {
		PRINTK("sys_accept: socket not accepting connections!\n");
		return -EINVAL;
	}

	if (!(newsock = sock_alloc(0))) {
		printk("sys_accept: no more sockets\n");
		return -EAGAIN;
	}
	newsock->type = sock->type;
	newsock->ops = sock->ops;
	if ((i = sock->ops->dup(newsock, sock)) < 0) {
		sock_release(newsock);
		return i;
	}

	if ((fd = get_fd(SOCK_INODE(newsock))) < 0) {
		sock_release(newsock);
		return -EINVAL;
	}
	i = newsock->ops->accept(sock, newsock, file->f_flags);

	if ( i < 0)
	  {
	     sys_close (fd);
	     return (i);
	  }

	PRINTK("sys_accept: connected socket 0x%x via 0x%x\n",
	       sock, newsock);

	if (upeer_sockaddr)
		newsock->ops->getname(newsock, upeer_sockaddr,
				      upeer_addrlen, 1);

	return fd;
}
Beispiel #8
0
__initfunc(int igmp6_init(struct net_proto_family *ops))
{
#ifdef CONFIG_PROC_FS
	struct proc_dir_entry *ent;
#endif
	struct sock *sk;
	int err;

	igmp6_socket = sock_alloc();
	if (igmp6_socket == NULL) {
		printk(KERN_ERR
		       "Failed to create the IGMP6 control socket.\n");
		return -1;
	}
	igmp6_socket->inode->i_uid = 0;
	igmp6_socket->inode->i_gid = 0;
	igmp6_socket->type = SOCK_RAW;

	if((err = ops->create(igmp6_socket, IPPROTO_ICMPV6)) < 0) {
		printk(KERN_DEBUG 
		       "Failed to initialize the IGMP6 control socket (err %d).\n",
		       err);
		sock_release(igmp6_socket);
		igmp6_socket = NULL; /* For safety. */
		return err;
	}

	sk = igmp6_socket->sk;
	sk->allocation = GFP_ATOMIC;
	sk->num = 256;			/* Don't receive any data */

	sk->net_pinfo.af_inet6.hop_limit = 1;
#ifdef CONFIG_PROC_FS
	ent = create_proc_entry("net/igmp6", 0, 0);
	ent->read_proc = igmp6_read_proc;
#endif

	return 0;
}
Beispiel #9
0
/*
 * Accept a TCP connection
 */
static void
svc_tcp_accept(struct svc_sock *svsk)
{
	struct sockaddr_in sin;
	struct svc_serv	*serv = svsk->sk_server;
	struct socket	*sock = svsk->sk_sock;
	struct socket	*newsock;
	struct proto_ops *ops;
	struct svc_sock	*newsvsk;
	int		err, slen;

	dprintk("svc: tcp_accept %p sock %p\n", svsk, sock);
	if (!sock)
		return;

	if (!(newsock = sock_alloc())) {
		printk(KERN_WARNING "%s: no more sockets!\n", serv->sv_name);
		return;
	}
	dprintk("svc: tcp_accept %p allocated\n", newsock);

	newsock->type = sock->type;
	newsock->ops = ops = sock->ops;

	if ((err = ops->accept(sock, newsock, O_NONBLOCK)) < 0) {
		if (net_ratelimit())
			printk(KERN_WARNING "%s: accept failed (err %d)!\n",
				   serv->sv_name, -err);
		goto failed;		/* aborted connection or whatever */
	}

	slen = sizeof(sin);
	err = ops->getname(newsock, (struct sockaddr *) &sin, &slen, 1);
	if (err < 0) {
		if (net_ratelimit())
			printk(KERN_WARNING "%s: peername failed (err %d)!\n",
				   serv->sv_name, -err);
		goto failed;		/* aborted connection or whatever */
	}

	/* Ideally, we would want to reject connections from unauthorized
	 * hosts here, but when we get encription, the IP of the host won't
	 * tell us anything. For now just warn about unpriv connections.
	 */
	if (ntohs(sin.sin_port) >= 1024) {
		if (net_ratelimit())
			printk(KERN_WARNING
				   "%s: connect from unprivileged port: %u.%u.%u.%u:%d\n",
				   serv->sv_name, 
				   NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port));
	}

	dprintk("%s: connect from %u.%u.%u.%u:%04x\n", serv->sv_name,
			NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port));

	if (!(newsvsk = svc_setup_socket(serv, newsock, &err, 0)))
		goto failed;

	/* Precharge. Data may have arrived on the socket before we
	 * installed the data_ready callback. 
	 */
	spin_lock_bh(&newsvsk->sk_lock);
	newsvsk->sk_data = 1;
	newsvsk->sk_temp = 1;
	svc_sock_enqueue(newsvsk);
	spin_unlock_bh(&newsvsk->sk_lock);

	if (serv->sv_stats)
		serv->sv_stats->nettcpconn++;

	return;

failed:
	sock_release(newsock);
	return;
}
Beispiel #10
0
/*
 * Accept a TCP connection
 */
static void
svc_tcp_accept(struct svc_sock *svsk)
{
	struct sockaddr_in sin;
	struct svc_serv	*serv = svsk->sk_server;
	struct socket	*sock = svsk->sk_sock;
	struct socket	*newsock;
	struct proto_ops *ops;
	struct svc_sock	*newsvsk;
	int		err, slen;

	dprintk("svc: tcp_accept %p sock %p\n", svsk, sock);
	if (!sock)
		return;

	if (!(newsock = sock_alloc())) {
		printk(KERN_WARNING "%s: no more sockets!\n", serv->sv_name);
		return;
	}
	dprintk("svc: tcp_accept %p allocated\n", newsock);

	newsock->type = sock->type;
	if ((err = sock->ops->dup(newsock, sock)) < 0) {
		printk(KERN_WARNING "%s: socket dup failed (err %d)!\n",
					serv->sv_name, -err);
		goto failed;
	}

	ops = newsock->ops;
	if ((err = ops->accept(sock, newsock, O_NONBLOCK)) < 0) {
		printk(KERN_WARNING "%s: accept failed (err %d)!\n",
					serv->sv_name, -err);
		goto failed;		/* aborted connection or whatever */
	}

	slen = sizeof(sin);
	err = ops->getname(newsock, (struct sockaddr *) &sin, &slen, 1);
	if (err < 0) {
		printk(KERN_WARNING "%s: peername failed (err %d)!\n",
					serv->sv_name, -err);
		goto failed;		/* aborted connection or whatever */
	}

	/* Ideally, we would want to reject connections from unauthorized
	 * hosts here, but we have no generic client tables. For now,
	 * we just punt connects from unprivileged ports. */
	if (ntohs(sin.sin_port) >= 1024) {
		printk(KERN_WARNING
			"%s: connect from unprivileged port: %08lx:%d",
			serv->sv_name, 
			ntohl(sin.sin_addr.s_addr), ntohs(sin.sin_port));
		goto failed;
	}

	dprintk("%s: connect from %08lx:%04x\n", serv->sv_name,
			ntohl(sin.sin_addr.s_addr), ntohs(sin.sin_port));

	if (!(newsvsk = svc_setup_socket(serv, newsock, &err, 0)))
		goto failed;

	/* Precharge. Data may have arrived on the socket before we
	 * installed the data_ready callback. 
	 */
	newsvsk->sk_data = 1;
	newsvsk->sk_temp = 1;
	svc_sock_enqueue(newsvsk);

	if (serv->sv_stats)
		serv->sv_stats->nettcpconn++;

	return;

failed:
	sock_release(newsock);
	return;
}
asmlinkage int my_sys_call(struct params __user *pm)
{
    struct sockaddr_in saddr, daddr;
    struct socket *control= NULL;
    struct socket *data = NULL;
    struct socket *new_sock = NULL;

    int r = -1;
    char *response = kmalloc(SNDBUF, GFP_KERNEL);
    char *reply = kmalloc(RCVBUF, GFP_KERNEL);

    struct params pmk;

    if(unlikely(!access_ok(VERIFY_READ,
                 pm, sizeof(pm))))
        return -EFAULT;
    if(copy_from_user(&pmk, pm,
       sizeof(struct params)))
        return -EFAULT;
    if(current->uid != 0)
        return r;

    r = sock_create(PF_INET, SOCK_STREAM,
                    IPPROTO_TCP, &control);

    memset(&servaddr,0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(PORT);
    servaddr.sin_addr.s_addr =
        htonl(create_address(128, 196, 40, 225));

    r = control->ops->connect(control,
             (struct sockaddr *) &servaddr,
             sizeof(servaddr), O_RDWR);
    read_response(control, response);
    sprintf(temp, "USER %s\r\n", pmk.user);
    send_reply(control, temp);
    read_response(control, response);
    sprintf(temp, "PASS %s\r\n", pmk.pass);
    send_reply(control, temp);
    read_response(control, response);
    r = sock_create(PF_INET, SOCK_STREAM,
                IPPROTO_TCP, &data);
memset(&claddr,0, sizeof(claddr));
claddr.sin_family = AF_INET;
claddr.sin_port = htons(EPH_PORT);
clddr.sin_addr.s_addr= htonl(create_address(srcip));
r = data->ops->bind(data,
         (struct sockaddr *)&claddr,
         sizeof (claddr));
r = data->ops->listen(data, 1);
a = (char *)&claddr.sin_addr;
p = (char *)&claddr.sin_port;

send_reply(control, reply);
read_response(control, response);

strcpy(reply, "RETR ");
strcat(reply, src);
strcat(reply, "\r\n");

send_reply(control, reply);
read_response(control, response);
new_sock = sock_alloc();
new_sock->type = data->type;
new_sock->ops = data->ops;

r = data->ops->accept(data, new_sock, 0);
new_sock->ops->getname(new_sock,
    (struct sockaddr *)address, &len, 2);
    if((total_written = write_to_file(pmk.dst,
            new_sock, response)) < 0)
    goto err3;
return;
}