/* 释放一个socket结构,并唤醒socket_wait_free队列 */ static void sock_release(struct socket *sock) { int oldstate; struct inode *inode; struct socket *peersock, *nextsock; DPRINTF((net_debug, "NET: sock_release: socket 0x%x, inode 0x%x\n", sock, SOCK_INODE(sock))); /* 设置socket的状态为正在关闭连接 */ if ((oldstate = sock->state) != SS_UNCONNECTED) sock->state = SS_DISCONNECTING; /* Wake up anyone waiting for connections. */ for (peersock = sock->iconn; peersock; peersock = nextsock) { nextsock = peersock->next; sock_release_peer(peersock); } /* * Wake up anyone we're connected to. First, we release the * protocol, to give it a chance to flush data, etc. */ peersock = (oldstate == SS_CONNECTED) ? sock->conn : NULL; if (sock->ops) sock->ops->release(sock, peersock); if (peersock) sock_release_peer(peersock); inode = SOCK_INODE(sock); sock->state = SS_FREE; /* this really releases us */ wake_up_interruptible(&socket_wait_free); /* We need to do this. If sock alloc was called we already have an inode. */ iput(inode); }
static struct socket * sock_alloc(int wait) { struct socket *sock; while (1) { cli(); for (sock = sockets; sock <= last_socket; ++sock) if (sock->state == SS_FREE) { sock->state = SS_UNCONNECTED; sti(); sock->flags = 0; sock->ops = NULL; sock->data = NULL; sock->conn = NULL; sock->iconn = NULL; /* * this really shouldn't be necessary, but * everything else depends on inodes, so we * grab it. * sleeps are also done on the i_wait member * of this inode. * the close system call will iput this inode * for us. */ if (!(SOCK_INODE(sock) = get_empty_inode())) { printk("sock_alloc: no more inodes\n"); sock->state = SS_FREE; return NULL; } SOCK_INODE(sock)->i_mode = S_IFSOCK; sock->wait = &SOCK_INODE(sock)->i_wait; PRINTK("sock_alloc: socket 0x%x, inode 0x%x\n", sock, SOCK_INODE(sock)); return sock; } sti(); if (!wait) return NULL; PRINTK("sock_alloc: no free sockets, sleeping...\n"); interruptible_sleep_on(&socket_wait_free); if (current->signal & ~current->blocked) { PRINTK("sock_alloc: sleep was interrupted\n"); return NULL; } PRINTK("sock_alloc: wakeup... trying again...\n"); } }
static int x25_seq_socket_show(struct seq_file *seq, void *v) { struct sock *s; struct x25_sock *x25; struct net_device *dev; const char *devname; if (v == SEQ_START_TOKEN) { seq_printf(seq, "dest_addr src_addr dev lci st vs vr " "va t t2 t21 t22 t23 Snd-Q Rcv-Q inode\n"); goto out; } s = sk_entry(v); x25 = x25_sk(s); if (!x25->neighbour || (dev = x25->neighbour->dev) == NULL) devname = "???"; else devname = x25->neighbour->dev->name; seq_printf(seq, "%-10s %-10s %-5s %3.3X %d %d %d %d %3lu %3lu " "%3lu %3lu %3lu %5d %5d %ld\n", !x25->dest_addr.x25_addr[0] ? "*" : x25->dest_addr.x25_addr, !x25->source_addr.x25_addr[0] ? "*" : x25->source_addr.x25_addr, devname, x25->lci & 0x0FFF, x25->state, x25->vs, x25->vr, x25->va, x25_display_timer(s) / HZ, x25->t2 / HZ, x25->t21 / HZ, x25->t22 / HZ, x25->t23 / HZ, sk_wmem_alloc_get(s), sk_rmem_alloc_get(s), s->sk_socket ? SOCK_INODE(s->sk_socket)->i_ino : 0L); out: return 0; }
unsigned int hook_func(unsigned int hooknum, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { int uid = -1; int index = 0; if (!skb->sk) { //printk(KERN_ERR "hook_func skb->sk = NULL"); return NF_ACCEPT; } else if(!skb->sk->sk_socket) { //printk(KERN_ERR "hook_func skb->sk->sk_socket = NULL"); return NF_ACCEPT; } else { struct inode *inode = SOCK_INODE(skb->sk->sk_socket); if (inode) { uid = inode->i_uid; if (10000 > uid) { return NF_ACCEPT; } //printk(KERN_ERR "hook_func, -----inode->i_uid = %d---------", uid); if (clientPid <= 0 ) { printk(KERN_ERR "hook_func, clientPid=%d", clientPid); return NF_ACCEPT; } index = uid - 10000; if (index >= 0 && index <= 9999 && uidArray[index] == 0) { uidArray[index] = 1; send_network_msg(uid); } } } return NF_ACCEPT; }
static void sock_release(struct socket *sock) { int oldstate; struct socket *peersock, *nextsock; PRINTK("sock_release: socket 0x%x, inode 0x%x\n", sock, SOCK_INODE(sock)); if ((oldstate = sock->state) != SS_UNCONNECTED) sock->state = SS_DISCONNECTING; /* * wake up anyone waiting for connections */ for (peersock = sock->iconn; peersock; peersock = nextsock) { nextsock = peersock->next; sock_release_peer(peersock); } /* * wake up anyone we're connected to. first, we release the * protocol, to give it a chance to flush data, etc. */ peersock = (oldstate == SS_CONNECTED) ? sock->conn : NULL; if (sock->ops) sock->ops->release(sock, peersock); if (peersock) sock_release_peer(peersock); sock->state = SS_FREE; /* this really releases us */ wake_up(&socket_wait_free); }
/* * Get__netinfo returns the length of that string. * * KNOWN BUGS * As in get_unix_netinfo, the buffer might be too small. If this * happens, get__netinfo returns only part of the available infos. */ static int get__netinfo(struct proto *pro, char *buffer, int format) { struct sock **s_array; struct sock *sp; char *pos=buffer; int i; int timer_active; unsigned long dest, src; unsigned short destp, srcp; s_array = pro->sock_array; pos+=sprintf(pos, "sl local_address rem_address st tx_queue rx_queue tr tm->when uid\n"); /* * This was very pretty but didn't work when a socket is destroyed at the wrong moment * (eg a syn recv socket getting a reset), or a memory timer destroy. Instead of playing * with timers we just concede defeat and cli(). */ for(i = 0; i < SOCK_ARRAY_SIZE; i++) { cli(); sp = s_array[i]; while(sp != NULL) { dest = sp->daddr; src = sp->saddr; destp = sp->dummy_th.dest; srcp = sp->dummy_th.source; /* Since we are Little Endian we need to swap the bytes :-( */ destp = ntohs(destp); srcp = ntohs(srcp); timer_active = del_timer(&sp->timer); if (!timer_active) sp->timer.expires = 0; pos+=sprintf(pos, "%2d: %08lX:%04X %08lX:%04X %02X %08lX:%08lX %02X:%08lX %08X %d\n", i, src, srcp, dest, destp, sp->state, format==0?sp->write_seq-sp->rcv_ack_seq:sp->rmem_alloc, format==0?sp->acked_seq-sp->copied_seq:sp->wmem_alloc, timer_active, sp->timer.expires, (unsigned) sp->retransmits, SOCK_INODE(sp->socket)->i_uid); if (timer_active) add_timer(&sp->timer); /* Is place in buffer too rare? then abort. */ if (pos > buffer+PAGE_SIZE-80) { printk("oops, too many %s sockets for netinfo.\n", pro->name); return(strlen(buffer)); } /* * All sockets with (port mod SOCK_ARRAY_SIZE) = i * are kept in sock_array[i], so we must follow the * 'next' link to get them all. */ sp = sp->next; } sti(); /* We only turn interrupts back on for a moment, but because the interrupt queues anything built up before this will clear before we jump back and cli, so its not as bad as it looks */ } return(strlen(buffer)); }
/* 创建一个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); }
struct socket * socki_lookup(struct inode *inode) { struct socket *sock; if ((sock = inode->i_socket) != NULL) { if (sock->state != SS_FREE && SOCK_INODE(sock) == inode) return sock; printk("socket.c: uhhuh. stale inode->i_socket pointer\n"); } for (sock = sockets; sock <= last_socket; ++sock) if (sock->state != SS_FREE && SOCK_INODE(sock) == inode) { printk("socket.c: uhhuh. Found socket despite no inode->i_socket pointer\n"); return(sock); } return(NULL); }
/* * 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; }
unsigned long sock_i_ino(struct sock *sk) { unsigned long ino; read_lock(&sk->sk_callback_lock); ino = sk->sk_socket ? SOCK_INODE(sk->sk_socket)->i_ino : 0; read_unlock(&sk->sk_callback_lock); return ino; }
int sock_i_uid(struct sock *sk) { int uid; read_lock(&sk->sk_callback_lock); uid = sk->sk_socket ? SOCK_INODE(sk->sk_socket)->i_uid : 0; read_unlock(&sk->sk_callback_lock); return uid; }
/* 查找一个空闲的struct socket结构,并初始化相应的关系 * 如sock中有inode节点指针,inode中有struct socket指针 * wait表示在获取socket结构的时候,该函数是不是阻塞的, * wait>0表示阻塞,=0表示非阻塞 */ static struct socket *sock_alloc(int wait) { struct socket *sock; while (1) { cli(); for (sock = sockets; sock <= last_socket; ++sock) { if (sock->state == SS_FREE) { /* 注意在socket系统调用完成后struct socket的状态为SS_UNCONNECTED */ sock->state = SS_UNCONNECTED; sti(); sock->flags = 0; sock->ops = NULL; sock->data = NULL; sock->conn = NULL; sock->iconn = NULL; /* * This really shouldn't be necessary, but everything * else depends on inodes, so we grab it. * Sleeps are also done on the i_wait member of this * inode. The close system call will iput this inode * for us. */ /* 此处给socket分配了一个inode,但是inode是空的, * 并没有包含有效数据的 */ if (!(SOCK_INODE(sock) = get_empty_inode())) { printk("NET: sock_alloc: no more inodes\n"); sock->state = SS_FREE; return(NULL); } /* 此时设置inode和socket之间的关系, * S_IFSOCK指明inode指向的时socket文件 */ SOCK_INODE(sock)->i_mode = S_IFSOCK; SOCK_INODE(sock)->i_uid = current->euid; SOCK_INODE(sock)->i_gid = current->egid; SOCK_INODE(sock)->i_socket = sock; sock->wait = &SOCK_INODE(sock)->i_wait; DPRINTF((net_debug, "NET: sock_alloc: sk 0x%x, ino 0x%x\n", sock, SOCK_INODE(sock))); return(sock); } } sti(); if (!wait) return(NULL); DPRINTF((net_debug, "NET: sock_alloc: no free sockets, sleeping...\n")); /* 如果没找到,则在socket_wait_free队列中睡眠,当有释放时,则唤醒该进程 */ interruptible_sleep_on(&socket_wait_free); if (current->signal & ~current->blocked) { DPRINTF((net_debug, "NET: sock_alloc: sleep was interrupted\n")); return(NULL); } DPRINTF((net_debug, "NET: sock_alloc: wakeup... trying again...\n")); } }
/* 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); }
static inline struct socket * socki_lookup(struct inode *inode) { struct socket *sock; for (sock = sockets; sock <= last_socket; ++sock) if (sock->state != SS_FREE && SOCK_INODE(sock) == inode) return sock; return NULL; }
/* 根据inode来查找struct socket结构 */ struct socket *socki_lookup(struct inode *inode) { struct socket *sock; /* 如果当前inode的i_socket不为空,且两者相互指向,则返回 */ if ((sock = inode->i_socket) != NULL) { if (sock->state != SS_FREE && SOCK_INODE(sock) == inode) return sock; printk("socket.c: uhhuh. stale inode->i_socket pointer\n"); } /* 如果inode当中没有struct socket的指针, * 则在socket数组中查找socket中inode指向参数inode的项 * 如果找到了则返回,否则返回为空。 */ for (sock = sockets; sock <= last_socket; ++sock) if (sock->state != SS_FREE && SOCK_INODE(sock) == inode) { printk("socket.c: uhhuh. Found socket despite no inode->i_socket pointer\n"); return(sock); } return(NULL); }
/* * 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; }
int atalk_get_info(char *buffer, char **start, off_t offset, int length, int dummy) { atalk_socket *s; int len=0; off_t pos=0; off_t begin=0; /* * Output the appletalk data for the /proc virtual fs. */ len += sprintf (buffer,"Type local_addr remote_addr tx_queue rx_queue st uid\n"); for (s = atalk_socket_list; s != NULL; s = s->next) { len += sprintf (buffer+len,"%02X ", s->type); len += sprintf (buffer+len,"%04X:%02X:%02X ", ntohs(s->protinfo.af_at.src_net), s->protinfo.af_at.src_node, s->protinfo.af_at.src_port); len += sprintf (buffer+len,"%04X:%02X:%02X ", ntohs(s->protinfo.af_at.dest_net), s->protinfo.af_at.dest_node, s->protinfo.af_at.dest_port); len += sprintf (buffer+len,"%08X:%08X ", s->wmem_alloc, s->rmem_alloc); len += sprintf (buffer+len,"%02X %d\n", s->state, SOCK_INODE(s->socket)->i_uid); /* Are we still dumping unwanted data then discard the record */ pos=begin+len; if(pos<offset) { len=0; /* Keep dumping into the buffer start */ begin=pos; } if(pos>offset+length) /* We have dumped enough */ break; } /* The data in question runs from begin to begin+len */ *start=buffer+(offset-begin); /* Start of wanted data */ len-=(offset-begin); /* Remove unwanted header data from length */ if(len>length) len=length; /* Remove unwanted tail data from length */ return len; }
static int atalk_seq_socket_show(struct seq_file *seq, void *v) { struct sock *s; struct atalk_sock *at; if (v == SEQ_START_TOKEN) { seq_printf(seq, "Type Local_addr Remote_addr Tx_queue " "Rx_queue St UID\n"); goto out; } s = v; at = at_sk(s); seq_printf(seq, "%02X %04X:%02X:%02X %04X:%02X:%02X %08X:%08X " "%02X %d\n", s->sk_type, ntohs(at->src_net), at->src_node, at->src_port, ntohs(at->dest_net), at->dest_node, at->dest_port, atomic_read(&s->sk_wmem_alloc), atomic_read(&s->sk_rmem_alloc), s->sk_state, SOCK_INODE(s->sk_socket)->i_uid); out: return 0; }