1*4958Swnj /* in_pcb.c 4.5 81/11/20 */ 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; 274951Swnj register struct inpcb *inp; 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) { 394951Swnj inp = head->inp_next; 404951Swnj for (; inp != head; inp = inp->inp_next) 414951Swnj if (inp->inp_laddr.s_addr == 424951Swnj sin->sin_addr.s_addr && 434951Swnj inp->inp_lport == lport && 444951Swnj inp->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) 534951Swnj return (0); 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; 654951Swnj for (inp = head->inp_next; inp != head; inp = inp->inp_next) 664951Swnj if (inp->inp_lport == head->inp_lport) 674951Swnj goto again; 684951Swnj lport = head->inp_lport; 694951Swnj gotport: 704951Swnj inp->inp_lport = lport; 714951Swnj insque(head, inp); 724951Swnj so->so_pcb = (caddr_t)inp; 73*4958Swnj sin = (struct sockaddr_in *)&so->so_addr; 74*4958Swnj sin->sin_family = AF_INET; 75*4958Swnj sin->sin_addr = inp->inp_laddr; 76*4958Swnj sin->sin_port = inp->inp_lport; 774951Swnj return (0); 784951Swnj bad2: 794951Swnj sbrelease(&so->so_snd); 804951Swnj bad: 814951Swnj m_free(m); 824951Swnj return (ENOBUFS); 834905Swnj } 844905Swnj 854951Swnj in_pcbsetpeer(inp, sin) 864951Swnj struct inpcb *inp; 874951Swnj struct sockaddr_in *sin; 884923Swnj { 894923Swnj 904951Swnj if (sin->sin_family != AF_INET) 914951Swnj return (EAFNOSUPPORT); 924951Swnj if (sin->sin_addr.s_addr == 0 || sin->sin_port == 0) 934951Swnj return (EADDRNOTAVAIL); 944951Swnj /* should check not already in use... */ 954951Swnj inp->inp_faddr = sin->sin_addr; 964951Swnj inp->inp_fport = sin->sin_port; 974923Swnj return (0); 984923Swnj } 994923Swnj 1004905Swnj in_pcbfree(inp) 1014905Swnj struct inpcb *inp; 1024905Swnj { 1034905Swnj struct socket *so = inp->inp_socket; 1044905Swnj 1054951Swnj if (so->so_state & SS_USERGONE) 1064905Swnj sofree(so); 1074905Swnj else 1084905Swnj so->so_pcb = 0; 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