1*5161Swnj /* in_pcb.c 4.11 81/12/02 */ 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" 105084Swnj #include "../net/in.h" 115084Swnj #include "../net/in_systm.h" 124951Swnj #include "../net/if.h" 135084Swnj #include "../net/in_pcb.h" 144905Swnj 154951Swnj /* 16*5161Swnj * Routines to manage internet protocol control blocks. 17*5161Swnj * 18*5161Swnj * At PRU_ATTACH time a protocol control block is allocated in 19*5161Swnj * in_pcballoc() and inserted on a doubly-linked list of such blocks 20*5161Swnj * for the protocol. A port address is either requested (and verified 21*5161Swnj * to not be in use) or assigned at this time. We also allocate 22*5161Swnj * space in the socket sockbuf structures here, although this is 23*5161Swnj * not a clearly correct place to put this function. 24*5161Swnj * 25*5161Swnj * A connectionless protocol will have its protocol control block 26*5161Swnj * removed at PRU_DETACH time, when the socket will be freed (freeing 27*5161Swnj * the space reserved) and the block will be removed from the list of 28*5161Swnj * blocks for its protocol. 29*5161Swnj * 30*5161Swnj * A connection-based protocol may be connected to a remote peer at 31*5161Swnj * PRU_CONNECT time through the routine in_pcbconnect(). In the normal 32*5161Swnj * case a PRU_DISCONNECT occurs causing a in_pcbdisconnect(). 33*5161Swnj * It is also possible that higher-level routines will opt out of the 34*5161Swnj * relationship with the connection before the connection shut down 35*5161Swnj * is complete. This often occurs in protocols like TCP where we must 36*5161Swnj * hold on to the protocol control block for a unreasonably long time 37*5161Swnj * after the connection is used up to avoid races in later connection 38*5161Swnj * establishment. To handle this we allow higher-level routines to 39*5161Swnj * disassociate themselves from the socket, marking it SS_USERGONE while 40*5161Swnj * the disconnect is in progress. We notice that this has happened 41*5161Swnj * when the disconnect is complete, and perform the PRU_DETACH operation, 42*5161Swnj * freeing the socket. 43*5161Swnj */ 44*5161Swnj 45*5161Swnj /* 464951Swnj * Allocate a protocol control block, space 474951Swnj * for send and receive data, and local host information. 484951Swnj * Return error. If no error make socket point at pcb. 494951Swnj */ 50*5161Swnj in_pcbattach(so, head, sndcc, rcvcc, sin) 514951Swnj struct socket *so; 524951Swnj struct inpcb *head; 534951Swnj int sndcc, rcvcc; 544951Swnj struct sockaddr_in *sin; 554905Swnj { 564905Swnj struct mbuf *m; 574983Swnj register struct inpcb *inp, *xp; 584951Swnj struct ifnet *ifp; 594951Swnj u_long lport; 604905Swnj 61*5161Swnj COUNT(IN_PCBATTACH); 624951Swnj if (sin) { 634951Swnj if (sin->sin_family != AF_INET) 644951Swnj return (EAFNOSUPPORT); 654951Swnj ifp = if_ifwithaddr(sin->sin_addr); 664951Swnj if (ifp == 0) 674951Swnj return (EADDRNOTAVAIL); 684951Swnj lport = sin->sin_port; 694951Swnj if (lport) { 704983Swnj xp = head->inp_next; 715107Swnj for (; xp != head; xp = xp->inp_next) 724983Swnj if (xp->inp_laddr.s_addr == 734951Swnj sin->sin_addr.s_addr && 744983Swnj xp->inp_lport == lport && 754983Swnj xp->inp_faddr.s_addr == 0) 764951Swnj return (EADDRINUSE); 774951Swnj } 784951Swnj } else { 794951Swnj ifp = if_ifwithaddr(ifnet->if_addr); 804951Swnj lport = 0; 814951Swnj } 824905Swnj m = m_getclr(M_WAIT); 834951Swnj if (m == 0) 844983Swnj return (ENOBUFS); 854951Swnj if (sbreserve(&so->so_snd, sndcc) == 0) 864951Swnj goto bad; 874951Swnj if (sbreserve(&so->so_rcv, rcvcc) == 0) 884951Swnj goto bad2; 894951Swnj inp = mtod(m, struct inpcb *); 904951Swnj inp->inp_laddr = ifp->if_addr; 914951Swnj if (lport) 924951Swnj goto gotport; 934951Swnj again: 944951Swnj if (head->inp_lport++ < 1024) 954951Swnj head->inp_lport = 1024; 964983Swnj for (xp = head->inp_next; xp != head; xp = xp->inp_next) 974983Swnj if (xp->inp_lport == head->inp_lport) 984951Swnj goto again; 99*5161Swnj lport = htons(head->inp_lport); 1004951Swnj gotport: 1014983Swnj inp->inp_socket = so; 1024951Swnj inp->inp_lport = lport; 1034983Swnj insque(inp, head); 1044951Swnj so->so_pcb = (caddr_t)inp; 1054958Swnj sin = (struct sockaddr_in *)&so->so_addr; 1064958Swnj sin->sin_family = AF_INET; 1074958Swnj sin->sin_addr = inp->inp_laddr; 1084958Swnj sin->sin_port = inp->inp_lport; 1094951Swnj return (0); 1104951Swnj bad2: 1114951Swnj sbrelease(&so->so_snd); 1124951Swnj bad: 1134967Swnj (void) m_free(m); 1144951Swnj return (ENOBUFS); 1154905Swnj } 1164905Swnj 117*5161Swnj in_pcbconnect(inp, sin) 1184951Swnj struct inpcb *inp; 1194951Swnj struct sockaddr_in *sin; 1204923Swnj { 1214923Swnj 122*5161Swnj COUNT(IN_PCBCONNECT); 1234951Swnj if (sin->sin_family != AF_INET) 1244951Swnj return (EAFNOSUPPORT); 1254951Swnj if (sin->sin_addr.s_addr == 0 || sin->sin_port == 0) 1264951Swnj return (EADDRNOTAVAIL); 1274951Swnj /* should check not already in use... */ 1284951Swnj inp->inp_faddr = sin->sin_addr; 1294951Swnj inp->inp_fport = sin->sin_port; 1304923Swnj return (0); 1314923Swnj } 1324923Swnj 133*5161Swnj in_pcbdisconnect(inp) 1344905Swnj struct inpcb *inp; 1354905Swnj { 136*5161Swnj 137*5161Swnj COUNT(IN_PCBDISCONNECT); 138*5161Swnj inp->inp_faddr.s_addr = 0; 139*5161Swnj if (inp->inp_socket->so_state & SS_USERGONE) 140*5161Swnj in_pcbdetach(inp); 141*5161Swnj } 142*5161Swnj 143*5161Swnj in_pcbdetach(inp) 144*5161Swnj struct inpcb *inp; 145*5161Swnj { 1464905Swnj struct socket *so = inp->inp_socket; 1474905Swnj 1485009Swnj so->so_pcb = 0; 1495009Swnj sofree(so); 1504983Swnj remque(inp); 1514907Swnj (void) m_free(dtom(inp)); 1524905Swnj } 1534905Swnj 154*5161Swnj /* 155*5161Swnj * Look for a control block to accept a segment. 156*5161Swnj * First choice is an exact address match. 157*5161Swnj * Second choice is a match of local address, with 158*5161Swnj * unspecified foreign address. 159*5161Swnj */ 1604907Swnj struct inpcb * 1614951Swnj in_pcblookup(head, faddr, fport, laddr, lport) 1624905Swnj struct inpcb *head; 1634951Swnj struct in_addr faddr, laddr; 1644905Swnj u_short fport, lport; 1654905Swnj { 1664905Swnj register struct inpcb *inp; 167*5161Swnj struct inpcb *match = 0; 1684905Swnj 169*5161Swnj for (inp = head->inp_next; inp != head; inp = inp->inp_next) { 170*5161Swnj if (inp->inp_laddr.s_addr != laddr.s_addr || 171*5161Swnj inp->inp_lport != lport) 172*5161Swnj continue; 173*5161Swnj if (inp->inp_faddr.s_addr == 0) { 174*5161Swnj match = inp; 175*5161Swnj continue; 176*5161Swnj } 1774951Swnj if (inp->inp_faddr.s_addr == faddr.s_addr && 178*5161Swnj inp->inp_fport == fport) 1794905Swnj return (inp); 180*5161Swnj } 181*5161Swnj return (match); 1824905Swnj } 183