1 /* in_pcb.c 4.4 81/11/20 */ 2 3 #include "../h/param.h" 4 #include "../h/systm.h" 5 #include "../h/dir.h" 6 #include "../h/user.h" 7 #include "../h/mbuf.h" 8 #include "../h/socket.h" 9 #include "../h/socketvar.h" 10 #include "../net/inet.h" 11 #include "../net/inet_systm.h" 12 #include "../net/if.h" 13 #include "../net/inet_pcb.h" 14 15 /* 16 * Allocate a protocol control block, space 17 * for send and receive data, and local host information. 18 * Return error. If no error make socket point at pcb. 19 */ 20 in_pcballoc(so, head, sndcc, rcvcc, sin) 21 struct socket *so; 22 struct inpcb *head; 23 int sndcc, rcvcc; 24 struct sockaddr_in *sin; 25 { 26 struct mbuf *m; 27 register struct inpcb *inp; 28 struct ifnet *ifp; 29 u_long lport; 30 31 if (sin) { 32 if (sin->sin_family != AF_INET) 33 return (EAFNOSUPPORT); 34 ifp = if_ifwithaddr(sin->sin_addr); 35 if (ifp == 0) 36 return (EADDRNOTAVAIL); 37 lport = sin->sin_port; 38 if (lport) { 39 inp = head->inp_next; 40 for (; inp != head; inp = inp->inp_next) 41 if (inp->inp_laddr.s_addr == 42 sin->sin_addr.s_addr && 43 inp->inp_lport == lport && 44 inp->inp_faddr.s_addr == 0) 45 return (EADDRINUSE); 46 } 47 } else { 48 ifp = if_ifwithaddr(ifnet->if_addr); 49 lport = 0; 50 } 51 m = m_getclr(M_WAIT); 52 if (m == 0) 53 return (0); 54 if (sbreserve(&so->so_snd, sndcc) == 0) 55 goto bad; 56 if (sbreserve(&so->so_rcv, rcvcc) == 0) 57 goto bad2; 58 inp = mtod(m, struct inpcb *); 59 inp->inp_laddr = ifp->if_addr; 60 if (lport) 61 goto gotport; 62 again: 63 if (head->inp_lport++ < 1024) 64 head->inp_lport = 1024; 65 for (inp = head->inp_next; inp != head; inp = inp->inp_next) 66 if (inp->inp_lport == head->inp_lport) 67 goto again; 68 lport = head->inp_lport; 69 gotport: 70 inp->inp_lport = lport; 71 insque(head, inp); 72 so->so_pcb = (caddr_t)inp; 73 return (0); 74 bad2: 75 sbrelease(&so->so_snd); 76 bad: 77 m_free(m); 78 return (ENOBUFS); 79 } 80 81 in_pcbsetpeer(inp, sin) 82 struct inpcb *inp; 83 struct sockaddr_in *sin; 84 { 85 86 if (sin->sin_family != AF_INET) 87 return (EAFNOSUPPORT); 88 if (sin->sin_addr.s_addr == 0 || sin->sin_port == 0) 89 return (EADDRNOTAVAIL); 90 /* should check not already in use... */ 91 inp->inp_faddr = sin->sin_addr; 92 inp->inp_fport = sin->sin_port; 93 return (0); 94 } 95 96 in_pcbfree(inp) 97 struct inpcb *inp; 98 { 99 struct socket *so = inp->inp_socket; 100 101 if (so->so_state & SS_USERGONE) 102 sofree(so); 103 else 104 so->so_pcb = 0; 105 (void) m_free(dtom(inp)); 106 } 107 108 struct inpcb * 109 in_pcblookup(head, faddr, fport, laddr, lport) 110 struct inpcb *head; 111 struct in_addr faddr, laddr; 112 u_short fport, lport; 113 { 114 register struct inpcb *inp; 115 116 for (inp = head->inp_next; inp != head; inp = inp->inp_next) 117 if (inp->inp_faddr.s_addr == faddr.s_addr && 118 inp->inp_fport == fport && 119 inp->inp_laddr.s_addr == laddr.s_addr && 120 inp->inp_lport == lport) 121 return (inp); 122 for (inp = head->inp_next; inp != head; inp = inp->inp_next) 123 if ((inp->inp_faddr.s_addr == faddr.s_addr || 124 inp->inp_faddr.s_addr == 0) && 125 (inp->inp_fport == fport || inp->inp_fport == 0) && 126 inp->inp_laddr.s_addr == laddr.s_addr && 127 (inp->inp_lport == lport || inp->inp_lport == 0)) 128 return (inp); 129 return (0); 130 } 131