static int ip_proto_bind (struct socket *sock, struct sockaddr *uaddr, int addr_len) { struct sockaddr_in addr; volatile struct sock *sk, *sk2; unsigned short snum; sk = sock->data; if (sk == NULL) { printk ("Warning: sock->data = NULL: %d\n" ,__LINE__); return (0); } /* check this error. */ if (sk->state != TCP_CLOSE) return (-EIO); verify_area (uaddr, addr_len); memcpy_fromfs (&addr, uaddr, min (sizeof (addr), addr_len)); if (addr.sin_family && addr.sin_family != AF_INET) return (-EIO); /* this needs to be changed. */ snum = net16(addr.sin_port); PRINTK ("bind sk =%X to port = %d\n", sk, snum); print_sk (sk); sk = sock->data; /* we can't just leave the socket bound wherever it is, it might be bound to a priveledged port. However, since there seems to be a bug here, we will leave it if the port is not priveledged(sp?) */ if (snum == 0) { if ( sk->num > PROT_SOCK) return (0); snum = get_new_socknum (sk->prot, 0); } if (snum <= PROT_SOCK && !suser()) return (-EPERM); if (my_ip_addr(addr.sin_addr.s_addr) || addr.sin_addr.s_addr == 0) sk->saddr = addr.sin_addr.s_addr; PRINTK ("sock_array[%d] = %X:\n", snum & (SOCK_ARRAY_SIZE -1), sk->prot->sock_array[snum & (SOCK_ARRAY_SIZE -1)]); print_sk (sk->prot->sock_array[snum & (SOCK_ARRAY_SIZE -1)]); /* make sure we are allowed to bind here. */ for (sk2 = sk->prot->sock_array[snum & (SOCK_ARRAY_SIZE -1)]; sk2 != NULL; sk2 = sk2->next) { if (sk2->num != snum) continue; if (sk2->saddr != sk->saddr) continue; if (!sk->reuse) return (-EADDRINUSE); if (!sk2->reuse) return (-EADDRINUSE); } remove_sock (sk); put_sock(snum, sk); sk->dummy_th.source = net16(sk->num); sk->daddr = 0; sk->dummy_th.dest = 0; return (0); }
static inline bool check_sock(void *data) { Sock *sock = (Sock*)data; if((curr_time - sock->last_pack_time) >= SOCK_TIME_OUT) { remove_sock(sock, true); return true; } return false; }
static int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) { struct sockaddr_in *addr=(struct sockaddr_in *)uaddr; struct sock *sk=(struct sock *)sock->data, *sk2; unsigned short snum = 0 /* Stoopid compiler.. this IS ok */; int chk_addr_ret; /* check this error. */ if (sk->state != TCP_CLOSE) return(-EIO); if(addr_len<sizeof(struct sockaddr_in)) return -EINVAL; if(sock->type != SOCK_RAW) { /* 验证sk已经加入到对应传输层协议的管理结构中 */ if (sk->num != 0) return(-EINVAL); snum = ntohs(addr->sin_port); /* * We can't just leave the socket bound wherever it is, it might * be bound to a privileged port. However, since there seems to * be a bug here, we will leave it if the port is not privileged. */ if (snum == 0) { snum = get_new_socknum(sk->prot, 0); } if (snum < PROT_SOCK && !suser()) return(-EACCES); } chk_addr_ret = ip_chk_addr(addr->sin_addr.s_addr); if (addr->sin_addr.s_addr != 0 && chk_addr_ret != IS_MYADDR && chk_addr_ret != IS_MULTICAST) return(-EADDRNOTAVAIL); /* Source address MUST be ours! */ if (chk_addr_ret || addr->sin_addr.s_addr == 0) sk->saddr = addr->sin_addr.s_addr; if(sock->type != SOCK_RAW) { /* Make sure we are allowed to bind here. */ cli(); for(sk2 = sk->prot->sock_array[snum & (SOCK_ARRAY_SIZE -1)]; sk2 != NULL; sk2 = sk2->next) { /* should be below! */ if (sk2->num != snum) continue; if (!sk->reuse) { sti(); return(-EADDRINUSE); } if (sk2->num != snum) continue; /* more than one */ if (sk2->saddr != sk->saddr) continue; /* socket per slot ! -FB */ if (!sk2->reuse || sk2->state==TCP_LISTEN) { sti(); return(-EADDRINUSE); } } sti(); remove_sock(sk); put_sock(snum, sk); sk->dummy_th.source = ntohs(sk->num); sk->daddr = 0; sk->dummy_th.dest = 0; } return(0); }
void destroy_sock(struct sock *sk) { struct sk_buff *skb; sk->inuse = 1; /* just to be safe.对sock结构上锁 */ /* 首先检查dead标志,只有dead=1时才表示sock结构等待释放 */ /* In case it's sleeping somewhere. */ if (!sk->dead) sk->write_space(sk); // sock如果出现SO_NOSPACE标志,需要唤醒异步等待sock的进程 remove_sock(sk); /* 移除sock连接使用的定时器 */ /* Now we can no longer get new packets. */ delete_timer(sk); // 移除通用定时器 /* Nor send them */ del_timer(&sk->retransmit_timer); // 移除重传定时器 /* 释放sock::partial指向的数据写缓冲 */ while ((skb = tcp_dequeue_partial(sk)) != NULL) { IS_SKB(skb); kfree_skb(skb, FREE_WRITE); } /* Cleanup up the write buffer. */ while((skb = skb_dequeue(&sk->write_queue)) != NULL) { IS_SKB(skb); kfree_skb(skb, FREE_WRITE); } /* * Don't discard received data until the user side kills its * half of the socket. */ if (sk->dead) { while((skb=skb_dequeue(&sk->receive_queue))!=NULL) { /* * This will take care of closing sockets that were * listening and didn't accept everything. */ if (skb->sk != NULL && skb->sk != sk) { /* 如果当前sock对应一个listen socket就需要关闭尚未完成创建的socket连接 * 这其中的sock可能是establish或者syn_recv状态 */ IS_SKB(skb); skb->sk->dead = 1; skb->sk->prot->close(skb->sk, 0); } IS_SKB(skb); kfree_skb(skb, FREE_READ); } } /* Now we need to clean up the send head. 清理重发队列 */ cli(); for(skb = sk->send_head; skb != NULL; ) { struct sk_buff *skb2; /* * We need to remove skb from the transmit queue, * or maybe the arp queue. */ if (skb->next && skb->prev) { /* printk("destroy_sock: unlinked skb\n");*/ IS_SKB(skb); skb_unlink(skb); } skb->dev = NULL; skb2 = skb->link3; // link3在TCP中构建重发队列 kfree_skb(skb, FREE_WRITE); skb = skb2; } sk->send_head = NULL; sti(); /* And now the backlog. */ while((skb=skb_dequeue(&sk->back_log))!=NULL) { /* this should never happen. */ /* printk("cleaning back_log\n");*/ kfree_skb(skb, FREE_READ); } /* Now if it has a half accepted/ closed socket. */ if (sk->pair) { sk->pair->dead = 1; sk->pair->prot->close(sk->pair, 0); sk->pair = NULL; } /* * Now if everything is gone we can free the socket * structure, otherwise we need to keep it around until * everything is gone. */ if (sk->dead && sk->rmem_alloc == 0 && sk->wmem_alloc == 0) { kfree_s((void *)sk,sizeof(*sk)); } else { /* this should never happen. */ /* actually it can if an ack has just been sent. */ sk->destroy = 1; sk->ack_backlog = 0; sk->inuse = 0; reset_timer(sk, TIME_DESTROY, SOCK_DESTROY_TIME); } }
void destroy_sock(volatile struct sock *sk) { struct sk_buff *skb; PRINTK ("destroying socket %X\n",sk); /* just to be safe. */ sk->inuse = 1; remove_sock (sk); /* now we can no longer get new packets. */ delete_timer((struct timer *)&sk->time_wait); /* cleanup up the write buffer. */ for (skb = sk->wfront; skb != NULL; ) { struct sk_buff *skb2; skb2=skb->next; free_skb(skb, FREE_WRITE); skb=skb2; } sk->wfront = NULL; if (sk->rqueue != NULL) { skb = sk->rqueue; do { struct sk_buff *skb2; skb2=skb->next; /* this will take care of closing sockets that were listening and didn't accept everything. */ if (skb->sk != NULL && skb->sk != sk) { skb->sk->dead = 1; skb->sk->prot->close (skb->sk, 0); } free_skb(skb, FREE_READ); skb=skb2; } while (skb != sk->rqueue); } sk->rqueue = NULL; /* now we need to clean up the send head. */ for (skb = sk->send_head; skb != NULL; ) { struct sk_buff *skb2; /* we need to remove skb from the transmit queue. */ cli(); /* see if it's in a transmit queue. */ if (skb->next != NULL) { if (skb->next != skb) { skb->next->prev = skb->prev; skb->prev->next = skb->next; } else { int i; for (i = 0; i < DEV_NUMBUFFS; i++) { if (skb->dev && skb->dev->buffs[i] == skb) { skb->dev->buffs[i]= NULL; break; } } } } sti(); skb2=skb->link3; free_skb(skb, FREE_WRITE); skb=skb2; } sk->send_head = NULL; /* and now the backlog. */ if (sk->back_log != NULL) { /* this should never happen. */ printk ("cleaning back_log. \n"); cli(); skb = sk->back_log; do { struct sk_buff *skb2; skb2=skb->next; free_skb(skb, FREE_READ); skb=skb2; } while (skb != sk->back_log); sti(); } sk->back_log = NULL; /* now if everything is gone we can free the socket structure, otherwise we need to keep it around until everything is gone. */ if (sk->rmem_alloc == 0 && sk->wmem_alloc == 0) { free_s ((void *)sk,sizeof (*sk)); } else { /* this should never happen. */ /* actually it can if an ack has just been sent. */ PRINTK ("possible memory leak in socket = %X\n", sk); print_sk (sk); sk->destroy = 1; sk->ack_backlog = 0; sk->inuse = 0; sk->time_wait.len = SOCK_DESTROY_TIME; sk->timeout = TIME_DESTROY; reset_timer ((struct timer *)&sk->time_wait); } }