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; }
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; }
/* 创建一个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); }
/* * 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; }
/* 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); }
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; }
/* * 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; }
__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; }
/* * 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; }
/* * 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; }