📄 sock.c
字号:
/* Check this error. */ if (len < sizeof(sin)) return(-EINVAL); sin.sin_family = AF_INET; sk = (struct sock *) sock->data; if (sk == NULL) { printk("Warning: sock->data = NULL: %d\n" ,__LINE__); return(0); } if (peer) { if (!tcp_connected(sk->state)) return(-ENOTCONN); sin.sin_port = sk->dummy_th.dest; sin.sin_addr.s_addr = sk->daddr; } else { sin.sin_port = sk->dummy_th.source; if (sk->saddr == 0) sin.sin_addr.s_addr = my_addr(); else sin.sin_addr.s_addr = sk->saddr; } len = sizeof(sin);/* verify_area(VERIFY_WRITE, uaddr, len); NOW DONE ABOVE */ memcpy_tofs(uaddr, &sin, sizeof(sin));/* verify_area(VERIFY_WRITE, uaddr_len, sizeof(len)); NOW DONE ABOVE */ put_fs_long(len, uaddr_len); return(0);}static intinet_read(struct socket *sock, char *ubuf, int size, int noblock){ struct sock *sk; sk = (struct sock *) sock->data; if (sk == NULL) { printk("Warning: sock->data = NULL: %d\n" ,__LINE__); return(0); } /* We may need to bind the socket. */ if (sk->num == 0) { sk->num = get_new_socknum(sk->prot, 0); if (sk->num == 0) return(-EAGAIN); put_sock(sk->num, sk); sk->dummy_th.source = ntohs(sk->num); } return(sk->prot->read(sk, (unsigned char *) ubuf, size, noblock,0));}static intinet_recv(struct socket *sock, void *ubuf, int size, int noblock, unsigned flags){ struct sock *sk; sk = (struct sock *) sock->data; if (sk == NULL) { printk("Warning: sock->data = NULL: %d\n" ,__LINE__); return(0); } /* We may need to bind the socket. */ if (sk->num == 0) { sk->num = get_new_socknum(sk->prot, 0); if (sk->num == 0) return(-EAGAIN); put_sock(sk->num, sk); sk->dummy_th.source = ntohs(sk->num); } return(sk->prot->read(sk, (unsigned char *) ubuf, size, noblock, flags));}static intinet_write(struct socket *sock, char *ubuf, int size, int noblock){ struct sock *sk; sk = (struct sock *) sock->data; if (sk == NULL) { printk("Warning: sock->data = NULL: %d\n" ,__LINE__); return(0); } if (sk->shutdown & SEND_SHUTDOWN) { send_sig(SIGPIPE, current, 1); return(-EPIPE); } /* We may need to bind the socket. */ if (sk->num == 0) { sk->num = get_new_socknum(sk->prot, 0); if (sk->num == 0) return(-EAGAIN); put_sock(sk->num, sk); sk->dummy_th.source = ntohs(sk->num); } return(sk->prot->write(sk, (unsigned char *) ubuf, size, noblock, 0));}static intinet_send(struct socket *sock, void *ubuf, int size, int noblock, unsigned flags){ struct sock *sk; sk = (struct sock *) sock->data; if (sk == NULL) { printk("Warning: sock->data = NULL: %d\n" ,__LINE__); return(0); } if (sk->shutdown & SEND_SHUTDOWN) { send_sig(SIGPIPE, current, 1); return(-EPIPE); } /* We may need to bind the socket. */ if (sk->num == 0) { sk->num = get_new_socknum(sk->prot, 0); if (sk->num == 0) return(-EAGAIN); put_sock(sk->num, sk); sk->dummy_th.source = ntohs(sk->num); } return(sk->prot->write(sk, (unsigned char *) ubuf, size, noblock, flags));}static intinet_sendto(struct socket *sock, void *ubuf, int size, int noblock, unsigned flags, struct sockaddr *sin, int addr_len){ struct sock *sk; sk = (struct sock *) sock->data; if (sk == NULL) { printk("Warning: sock->data = NULL: %d\n" ,__LINE__); return(0); } if (sk->shutdown & SEND_SHUTDOWN) { send_sig(SIGPIPE, current, 1); return(-EPIPE); } if (sk->prot->sendto == NULL) return(-EOPNOTSUPP); /* We may need to bind the socket. */ if (sk->num == 0) { sk->num = get_new_socknum(sk->prot, 0); if (sk->num == 0) return(-EAGAIN); put_sock(sk->num, sk); sk->dummy_th.source = ntohs(sk->num); } return(sk->prot->sendto(sk, (unsigned char *) ubuf, size, noblock, flags, (struct sockaddr_in *)sin, addr_len));}static intinet_recvfrom(struct socket *sock, void *ubuf, int size, int noblock, unsigned flags, struct sockaddr *sin, int *addr_len ){ struct sock *sk; sk = (struct sock *) sock->data; if (sk == NULL) { printk("Warning: sock->data = NULL: %d\n" ,__LINE__); return(0); } if (sk->prot->recvfrom == NULL) return(-EOPNOTSUPP); /* We may need to bind the socket. */ if (sk->num == 0) { sk->num = get_new_socknum(sk->prot, 0); if (sk->num == 0) return(-EAGAIN); put_sock(sk->num, sk); sk->dummy_th.source = ntohs(sk->num); } return(sk->prot->recvfrom(sk, (unsigned char *) ubuf, size, noblock, flags, (struct sockaddr_in*)sin, addr_len));}static intinet_shutdown(struct socket *sock, int how){ struct sock *sk; /* * This should really check to make sure * the socket is a TCP socket. */ how++; /* maps 0->1 has the advantage of making bit 1 rcvs and 1->2 bit 2 snds. 2->3 */ if (how & ~SHUTDOWN_MASK) return(-EINVAL); sk = (struct sock *) sock->data; if (sk == NULL) { printk("Warning: sock->data = NULL: %d\n" ,__LINE__); return(0); } if (sock->state == SS_CONNECTING && sk->state == TCP_ESTABLISHED) sock->state = SS_CONNECTED; if (!tcp_connected(sk->state)) return(-ENOTCONN); sk->shutdown |= how; if (sk->prot->shutdown) sk->prot->shutdown(sk, how); return(0);}static intinet_select(struct socket *sock, int sel_type, select_table *wait ){ struct sock *sk; sk = (struct sock *) sock->data; if (sk == NULL) { printk("Warning: sock->data = NULL: %d\n" ,__LINE__); return(0); } if (sk->prot->select == NULL) { DPRINTF((DBG_INET, "select on non-selectable socket.\n")); return(0); } return(sk->prot->select(sk, sel_type, wait));}static intinet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg){ struct sock *sk; int err; DPRINTF((DBG_INET, "INET: in inet_ioctl\n")); sk = NULL; if (sock && (sk = (struct sock *) sock->data) == NULL) { printk("AF_INET: Warning: sock->data = NULL: %d\n" , __LINE__); return(0); } switch(cmd) { case FIOSETOWN: case SIOCSPGRP: err=verify_area(VERIFY_READ,(int *)arg,sizeof(long)); if(err) return err; if (sk) sk->proc = get_fs_long((int *) arg); return(0); case FIOGETOWN: case SIOCGPGRP: if (sk) { err=verify_area(VERIFY_WRITE,(void *) arg, sizeof(long)); if(err) return err; put_fs_long(sk->proc,(int *)arg); } return(0);#if 0 /* FIXME: */ case SIOCATMARK: printk("AF_INET: ioctl(SIOCATMARK, 0x%08X)\n",(void *) arg); return(-EINVAL);#endif case DDIOCSDBG: return(dbg_ioctl((void *) arg, DBG_INET)); case SIOCADDRT: case SIOCADDRTOLD: case SIOCDELRT: case SIOCDELRTOLD: return(rt_ioctl(cmd,(void *) arg)); case SIOCDARP: case SIOCGARP: case SIOCSARP: return(arp_ioctl(cmd,(void *) arg)); case IP_SET_DEV: case SIOCGIFCONF: case SIOCGIFFLAGS: case SIOCSIFFLAGS: case SIOCGIFADDR: case SIOCSIFADDR: case SIOCGIFDSTADDR: case SIOCSIFDSTADDR: case SIOCGIFBRDADDR: case SIOCSIFBRDADDR: case SIOCGIFNETMASK: case SIOCSIFNETMASK: case SIOCGIFMETRIC: case SIOCSIFMETRIC: case SIOCGIFMEM: case SIOCSIFMEM: case SIOCGIFMTU: case SIOCSIFMTU: case SIOCSIFLINK: case SIOCGIFHWADDR: return(dev_ioctl(cmd,(void *) arg)); default: if (!sk || !sk->prot->ioctl) return(-EINVAL); return(sk->prot->ioctl(sk, cmd, arg)); } /*NOTREACHED*/ return(0);}struct sk_buff *sock_wmalloc(struct sock *sk, unsigned long size, int force, int priority){ if (sk) { if (sk->wmem_alloc + size < sk->sndbuf || force) { struct sk_buff * c = alloc_skb(size, priority); if (c) { cli(); sk->wmem_alloc+= size; sti(); } return c; } DPRINTF((DBG_INET, "sock_wmalloc(%X,%d,%d,%d) returning NULL\n", sk, size, force, priority)); return(NULL); } return(alloc_skb(size, priority));}struct sk_buff *sock_rmalloc(struct sock *sk, unsigned long size, int force, int priority){ if (sk) { if (sk->rmem_alloc + size < sk->rcvbuf || force) { struct sk_buff *c = alloc_skb(size, priority); if (c) { cli(); sk->rmem_alloc += size; sti(); } return(c); } DPRINTF((DBG_INET, "sock_rmalloc(%X,%d,%d,%d) returning NULL\n", sk,size,force, priority)); return(NULL); } return(alloc_skb(size, priority));}unsigned longsock_rspace(struct sock *sk){ int amt; if (sk != NULL) { if (sk->rmem_alloc >= sk->rcvbuf-2*MIN_WINDOW) return(0); amt = min((sk->rcvbuf-sk->rmem_alloc)/2-MIN_WINDOW, MAX_WINDOW); if (amt < 0) return(0); return(amt); } return(0);}unsigned longsock_wspace(struct sock *sk){ if (sk != NULL) { if (sk->shutdown & SEND_SHUTDOWN) return(0); if (sk->wmem_alloc >= sk->sndbuf) return(0); return(sk->sndbuf-sk->wmem_alloc ); } return(0);}voidsock_wfree(struct sock *sk, void *mem, unsigned long size){ DPRINTF((DBG_INET, "sock_wfree(sk=%X, mem=%X, size=%d)\n", sk, mem, size)); IS_SKB(mem); kfree_skbmem(mem, size); if (sk) { sk->wmem_alloc -= size; /* In case it might be waiting for more memory. */ if (!sk->dead) sk->write_space(sk); if (sk->destroy && sk->wmem_alloc == 0 && sk->rmem_alloc == 0) { DPRINTF((DBG_INET, "recovered lost memory, sock = %X\n", sk)); } return; }}voidsock_rfree(struct sock *sk, void *mem, unsigned long size){ DPRINTF((DBG_INET, "sock_rfree(sk=%X, mem=%X, size=%d)\n", sk, mem, size)); IS_SKB(mem); kfree_skbmem(mem, size); if (sk) { sk->rmem_alloc -= size; if (sk->destroy && sk->wmem_alloc == 0 && sk->rmem_alloc == 0) { DPRINTF((DBG_INET, "recovered lot memory, sock = %X\n", sk)); } }}/* * This routine must find a socket given a TCP or UDP header. * Everyhting is assumed to be in net order. */struct sock *get_sock(struct proto *prot, unsigned short num, unsigned long raddr, unsigned short rnum, unsigned long laddr){ struct sock *s; unsigned short hnum; hnum = ntohs(num); DPRINTF((DBG_INET, "get_sock(prot=%X, num=%d, raddr=%X, rnum=%d, laddr=%X)\n", prot, num, raddr, rnum, laddr)); /* * SOCK_ARRAY_SIZE must be a power of two. This will work better * than a prime unless 3 or more sockets end up using the same * array entry. This should not be a problem because most * well known sockets don't overlap that much, and for * the other ones, we can just be careful about picking our * socket number when we choose an arbitrary one. */ for(s = prot->sock_array[hnum & (SOCK_ARRAY_SIZE - 1)]; s != NULL; s = s->next) { if (s->num != hnum) continue; if(s->dead && (s->state == TCP_CLOSE)) continue; if(prot == &udp_prot) return s; if(ip_addr_match(s->daddr,raddr)==0) continue; if (s->dummy_th.dest != rnum && s->dummy_th.dest != 0) continue; if(ip_addr_match(s->saddr,laddr) == 0) continue; return(s); } return(NULL);}void release_sock(struct sock *sk){ if (!sk) { printk("sock.c: release_sock sk == NULL\n"); return; } if (!sk->prot) {/* printk("sock.c: release_sock sk->prot == NULL\n"); */ return; } if (sk->blog) return; /* See if we have any packets built up. */ cli(); sk->inuse = 1; while(sk->back_log != NULL) { struct sk_buff *skb; sk->blog = 1; skb =(struct sk_buff *)sk->back_log; DPRINTF((DBG_INET, "release_sock: skb = %X:\n", skb)); if (skb->next != skb) { sk->back_log = skb->next; skb->prev->next = skb->next; skb->next->prev = skb->prev; } else { sk->back_log = NULL; } sti(); DPRINTF((DBG_INET, "sk->back_log = %X\n", sk->back_log)); if (sk->prot->rcv) sk->prot->rcv(skb, skb->dev, sk->opt, skb->saddr, skb->len, skb->daddr, 1, /* Only used for/by raw sockets. */ (struct inet_protocol *)sk->pair); cli(); } sk->blog = 0; sk->inuse = 0; sti(); if (sk->dead && sk->state == TCP_CLOSE) { /* Should be about 2 rtt's */ reset_timer(sk, TIME_DONE, min(sk->rtt * 2, TCP_DONE_TIME)); }}static intinet_fioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ int minor, ret; /* Extract the minor number on which we work. */ minor = MINOR(inode->i_rdev); if (minor != 0) return(-ENODEV); /* Now dispatch on the minor device. */ switch(minor) { case 0: /* INET */ ret = inet_ioctl(NULL, cmd, arg); break; case 1: /* IP */ ret = ip_ioctl(NULL, cmd, arg); break; case 2: /* ICMP */ ret = icmp_ioctl(NULL, cmd, arg); break; case 3: /* TCP */ ret = tcp_ioctl(NULL, cmd, arg); break; case 4: /* UDP */ ret = udp_ioctl(NULL, cmd, arg); break; default: ret = -ENODEV; } return(ret);}static struct file_operations inet_fops = { NULL, /* LSEEK */ NULL, /* READ */ NULL, /* WRITE */ NULL, /* READDIR */ NULL, /* SELECT */ inet_fioctl, /* IOCTL */ NULL, /* MMAP */ NULL, /* OPEN */ NULL /* CLOSE */};static struct proto_ops inet_proto_ops = { AF_INET, inet_create, inet_dup, inet_release, inet_bind, inet_connect, inet_socketpair, inet_accept, inet_getname, inet_read, inet_write, inet_select, inet_ioctl, inet_listen, inet_send, inet_recv, inet_sendto, inet_recvfrom, inet_shutdown, inet_setsockopt, inet_getsockopt, inet_fcntl,};extern unsigned long seq_offset;/* Called by ddi.c on kernel startup. */void inet_proto_init(struct ddi_proto *pro){ struct inet_protocol *p; int i; printk("Swansea University Computer Society Net2Debugged [1.30]\n"); /* Set up our UNIX VFS major device. */ if (register_chrdev(AF_INET_MAJOR, "af_inet", &inet_fops) < 0) { printk("%s: cannot register major device %d!\n", pro->name, AF_INET_MAJOR); return; } /* Tell SOCKET that we are alive... */ (void) sock_register(inet_proto_ops.family, &inet_proto_ops); seq_offset = CURRENT_TIME*250; /* Add all the protocols. */ for(i = 0; i < SOCK_ARRAY_SIZE; i++) { tcp_prot.sock_array[i] = NULL; udp_prot.sock_array[i] = NULL; raw_prot.sock_array[i] = NULL; } printk("IP Protocols: "); for(p = inet_protocol_base; p != NULL;) { struct inet_protocol *tmp; tmp = (struct inet_protocol *) p->next; inet_add_protocol(p); printk("%s%s",p->name,tmp?", ":"\n"); p = tmp; } /* Initialize the DEV module. */ dev_init(); /* Initialize the "Buffer Head" pointers. */ bh_base[INET_BH].routine = inet_bh;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -