1 /* in_pcb.c 4.7 81/11/21 */ 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, *xp; 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 xp = head->inp_next; 40 for (; xp != head; xp = inp->inp_next) 41 if (xp->inp_laddr.s_addr == 42 sin->sin_addr.s_addr && 43 xp->inp_lport == lport && 44 xp->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 (ENOBUFS); 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 (xp = head->inp_next; xp != head; xp = xp->inp_next) 66 if (xp->inp_lport == head->inp_lport) 67 goto again; 68 lport = head->inp_lport; 69 gotport: 70 inp->inp_socket = so; 71 inp->inp_lport = lport; 72 insque(inp, head); 73 so->so_pcb = (caddr_t)inp; 74 sin = (struct sockaddr_in *)&so->so_addr; 75 sin->sin_family = AF_INET; 76 sin->sin_addr = inp->inp_laddr; 77 sin->sin_port = inp->inp_lport; 78 return (0); 79 bad2: 80 sbrelease(&so->so_snd); 81 bad: 82 (void) m_free(m); 83 return (ENOBUFS); 84 } 85 86 in_pcbsetpeer(inp, sin) 87 struct inpcb *inp; 88 struct sockaddr_in *sin; 89 { 90 91 if (sin->sin_family != AF_INET) 92 return (EAFNOSUPPORT); 93 if (sin->sin_addr.s_addr == 0 || sin->sin_port == 0) 94 return (EADDRNOTAVAIL); 95 /* should check not already in use... */ 96 inp->inp_faddr = sin->sin_addr; 97 inp->inp_fport = sin->sin_port; 98 return (0); 99 } 100 101 in_pcbfree(inp) 102 struct inpcb *inp; 103 { 104 struct socket *so = inp->inp_socket; 105 106 if (so->so_state & SS_USERGONE) 107 sofree(so); 108 else 109 so->so_pcb = 0; 110 remque(inp); 111 (void) m_free(dtom(inp)); 112 } 113 114 struct inpcb * 115 in_pcblookup(head, faddr, fport, laddr, lport) 116 struct inpcb *head; 117 struct in_addr faddr, laddr; 118 u_short fport, lport; 119 { 120 register struct inpcb *inp; 121 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_fport == fport && 125 inp->inp_laddr.s_addr == laddr.s_addr && 126 inp->inp_lport == lport) 127 return (inp); 128 for (inp = head->inp_next; inp != head; inp = inp->inp_next) 129 if ((inp->inp_faddr.s_addr == faddr.s_addr || 130 inp->inp_faddr.s_addr == 0) && 131 (inp->inp_fport == fport || inp->inp_fport == 0) && 132 inp->inp_laddr.s_addr == laddr.s_addr && 133 (inp->inp_lport == lport || inp->inp_lport == 0)) 134 return (inp); 135 return (0); 136 } 137