1*4983Swnj /* in_pcb.c 4.7 81/11/21 */ 24905Swnj 34905Swnj #include "../h/param.h" 44951Swnj #include "../h/systm.h" 54951Swnj #include "../h/dir.h" 64951Swnj #include "../h/user.h" 74905Swnj #include "../h/mbuf.h" 84905Swnj #include "../h/socket.h" 94905Swnj #include "../h/socketvar.h" 104905Swnj #include "../net/inet.h" 114905Swnj #include "../net/inet_systm.h" 124951Swnj #include "../net/if.h" 134907Swnj #include "../net/inet_pcb.h" 144905Swnj 154951Swnj /* 164951Swnj * Allocate a protocol control block, space 174951Swnj * for send and receive data, and local host information. 184951Swnj * Return error. If no error make socket point at pcb. 194951Swnj */ 204951Swnj in_pcballoc(so, head, sndcc, rcvcc, sin) 214951Swnj struct socket *so; 224951Swnj struct inpcb *head; 234951Swnj int sndcc, rcvcc; 244951Swnj struct sockaddr_in *sin; 254905Swnj { 264905Swnj struct mbuf *m; 27*4983Swnj register struct inpcb *inp, *xp; 284951Swnj struct ifnet *ifp; 294951Swnj u_long lport; 304905Swnj 314951Swnj if (sin) { 324951Swnj if (sin->sin_family != AF_INET) 334951Swnj return (EAFNOSUPPORT); 344951Swnj ifp = if_ifwithaddr(sin->sin_addr); 354951Swnj if (ifp == 0) 364951Swnj return (EADDRNOTAVAIL); 374951Swnj lport = sin->sin_port; 384951Swnj if (lport) { 39*4983Swnj xp = head->inp_next; 40*4983Swnj for (; xp != head; xp = inp->inp_next) 41*4983Swnj if (xp->inp_laddr.s_addr == 424951Swnj sin->sin_addr.s_addr && 43*4983Swnj xp->inp_lport == lport && 44*4983Swnj xp->inp_faddr.s_addr == 0) 454951Swnj return (EADDRINUSE); 464951Swnj } 474951Swnj } else { 484951Swnj ifp = if_ifwithaddr(ifnet->if_addr); 494951Swnj lport = 0; 504951Swnj } 514905Swnj m = m_getclr(M_WAIT); 524951Swnj if (m == 0) 53*4983Swnj return (ENOBUFS); 544951Swnj if (sbreserve(&so->so_snd, sndcc) == 0) 554951Swnj goto bad; 564951Swnj if (sbreserve(&so->so_rcv, rcvcc) == 0) 574951Swnj goto bad2; 584951Swnj inp = mtod(m, struct inpcb *); 594951Swnj inp->inp_laddr = ifp->if_addr; 604951Swnj if (lport) 614951Swnj goto gotport; 624951Swnj again: 634951Swnj if (head->inp_lport++ < 1024) 644951Swnj head->inp_lport = 1024; 65*4983Swnj for (xp = head->inp_next; xp != head; xp = xp->inp_next) 66*4983Swnj if (xp->inp_lport == head->inp_lport) 674951Swnj goto again; 684951Swnj lport = head->inp_lport; 694951Swnj gotport: 70*4983Swnj inp->inp_socket = so; 714951Swnj inp->inp_lport = lport; 72*4983Swnj insque(inp, head); 734951Swnj so->so_pcb = (caddr_t)inp; 744958Swnj sin = (struct sockaddr_in *)&so->so_addr; 754958Swnj sin->sin_family = AF_INET; 764958Swnj sin->sin_addr = inp->inp_laddr; 774958Swnj sin->sin_port = inp->inp_lport; 784951Swnj return (0); 794951Swnj bad2: 804951Swnj sbrelease(&so->so_snd); 814951Swnj bad: 824967Swnj (void) m_free(m); 834951Swnj return (ENOBUFS); 844905Swnj } 854905Swnj 864951Swnj in_pcbsetpeer(inp, sin) 874951Swnj struct inpcb *inp; 884951Swnj struct sockaddr_in *sin; 894923Swnj { 904923Swnj 914951Swnj if (sin->sin_family != AF_INET) 924951Swnj return (EAFNOSUPPORT); 934951Swnj if (sin->sin_addr.s_addr == 0 || sin->sin_port == 0) 944951Swnj return (EADDRNOTAVAIL); 954951Swnj /* should check not already in use... */ 964951Swnj inp->inp_faddr = sin->sin_addr; 974951Swnj inp->inp_fport = sin->sin_port; 984923Swnj return (0); 994923Swnj } 1004923Swnj 1014905Swnj in_pcbfree(inp) 1024905Swnj struct inpcb *inp; 1034905Swnj { 1044905Swnj struct socket *so = inp->inp_socket; 1054905Swnj 1064951Swnj if (so->so_state & SS_USERGONE) 1074905Swnj sofree(so); 1084905Swnj else 1094905Swnj so->so_pcb = 0; 110*4983Swnj remque(inp); 1114907Swnj (void) m_free(dtom(inp)); 1124905Swnj } 1134905Swnj 1144907Swnj struct inpcb * 1154951Swnj in_pcblookup(head, faddr, fport, laddr, lport) 1164905Swnj struct inpcb *head; 1174951Swnj struct in_addr faddr, laddr; 1184905Swnj u_short fport, lport; 1194905Swnj { 1204905Swnj register struct inpcb *inp; 1214905Swnj 1224907Swnj for (inp = head->inp_next; inp != head; inp = inp->inp_next) 1234951Swnj if (inp->inp_faddr.s_addr == faddr.s_addr && 1244905Swnj inp->inp_fport == fport && 1254951Swnj inp->inp_laddr.s_addr == laddr.s_addr && 1264905Swnj inp->inp_lport == lport) 1274905Swnj return (inp); 1284907Swnj for (inp = head->inp_next; inp != head; inp = inp->inp_next) 1294951Swnj if ((inp->inp_faddr.s_addr == faddr.s_addr || 1304951Swnj inp->inp_faddr.s_addr == 0) && 1314905Swnj (inp->inp_fport == fport || inp->inp_fport == 0) && 1324951Swnj inp->inp_laddr.s_addr == laddr.s_addr && 1334905Swnj (inp->inp_lport == lport || inp->inp_lport == 0)) 1344905Swnj return (inp); 1354905Swnj return (0); 1364905Swnj } 137