1*5009Swnj /* in_pcb.c 4.8 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; 274983Swnj 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) { 394983Swnj xp = head->inp_next; 404983Swnj for (; xp != head; xp = inp->inp_next) 414983Swnj if (xp->inp_laddr.s_addr == 424951Swnj sin->sin_addr.s_addr && 434983Swnj xp->inp_lport == lport && 444983Swnj 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) 534983Swnj 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; 654983Swnj for (xp = head->inp_next; xp != head; xp = xp->inp_next) 664983Swnj if (xp->inp_lport == head->inp_lport) 674951Swnj goto again; 684951Swnj lport = head->inp_lport; 694951Swnj gotport: 704983Swnj inp->inp_socket = so; 714951Swnj inp->inp_lport = lport; 724983Swnj 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 106*5009Swnj so->so_pcb = 0; 107*5009Swnj sofree(so); 1084983Swnj remque(inp); 1094907Swnj (void) m_free(dtom(inp)); 1104905Swnj } 1114905Swnj 1124907Swnj struct inpcb * 1134951Swnj in_pcblookup(head, faddr, fport, laddr, lport) 1144905Swnj struct inpcb *head; 1154951Swnj struct in_addr faddr, laddr; 1164905Swnj u_short fport, lport; 1174905Swnj { 1184905Swnj register struct inpcb *inp; 1194905Swnj 1204907Swnj for (inp = head->inp_next; inp != head; inp = inp->inp_next) 1214951Swnj if (inp->inp_faddr.s_addr == faddr.s_addr && 1224905Swnj inp->inp_fport == fport && 1234951Swnj inp->inp_laddr.s_addr == laddr.s_addr && 1244905Swnj inp->inp_lport == lport) 1254905Swnj return (inp); 1264907Swnj for (inp = head->inp_next; inp != head; inp = inp->inp_next) 1274951Swnj if ((inp->inp_faddr.s_addr == faddr.s_addr || 1284951Swnj inp->inp_faddr.s_addr == 0) && 1294905Swnj (inp->inp_fport == fport || inp->inp_fport == 0) && 1304951Swnj inp->inp_laddr.s_addr == laddr.s_addr && 1314905Swnj (inp->inp_lport == lport || inp->inp_lport == 0)) 1324905Swnj return (inp); 1334905Swnj return (0); 1344905Swnj } 135