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