xref: /csrg-svn/sys/netinet/in_pcb.c (revision 4951)
1*4951Swnj /* in_pcb.c 4.4 81/11/20 */
24905Swnj 
34905Swnj #include "../h/param.h"
4*4951Swnj #include "../h/systm.h"
5*4951Swnj #include "../h/dir.h"
6*4951Swnj #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"
12*4951Swnj #include "../net/if.h"
134907Swnj #include "../net/inet_pcb.h"
144905Swnj 
15*4951Swnj /*
16*4951Swnj  * Allocate a protocol control block, space
17*4951Swnj  * for send and receive data, and local host information.
18*4951Swnj  * Return error.  If no error make socket point at pcb.
19*4951Swnj  */
20*4951Swnj in_pcballoc(so, head, sndcc, rcvcc, sin)
21*4951Swnj 	struct socket *so;
22*4951Swnj 	struct inpcb *head;
23*4951Swnj 	int sndcc, rcvcc;
24*4951Swnj 	struct sockaddr_in *sin;
254905Swnj {
264905Swnj 	struct mbuf *m;
27*4951Swnj 	register struct inpcb *inp;
28*4951Swnj 	struct ifnet *ifp;
29*4951Swnj 	u_long lport;
304905Swnj 
31*4951Swnj 	if (sin) {
32*4951Swnj 		if (sin->sin_family != AF_INET)
33*4951Swnj 			return (EAFNOSUPPORT);
34*4951Swnj 		ifp = if_ifwithaddr(sin->sin_addr);
35*4951Swnj 		if (ifp == 0)
36*4951Swnj 			return (EADDRNOTAVAIL);
37*4951Swnj 		lport = sin->sin_port;
38*4951Swnj 		if (lport) {
39*4951Swnj 			inp = head->inp_next;
40*4951Swnj 			for (; inp != head; inp = inp->inp_next)
41*4951Swnj 				if (inp->inp_laddr.s_addr ==
42*4951Swnj 				    sin->sin_addr.s_addr &&
43*4951Swnj 				    inp->inp_lport == lport &&
44*4951Swnj 				    inp->inp_faddr.s_addr == 0)
45*4951Swnj 					return (EADDRINUSE);
46*4951Swnj 		}
47*4951Swnj 	} else {
48*4951Swnj 		ifp = if_ifwithaddr(ifnet->if_addr);
49*4951Swnj 		lport = 0;
50*4951Swnj 	}
514905Swnj 	m = m_getclr(M_WAIT);
52*4951Swnj 	if (m == 0)
53*4951Swnj 		return (0);
54*4951Swnj 	if (sbreserve(&so->so_snd, sndcc) == 0)
55*4951Swnj 		goto bad;
56*4951Swnj 	if (sbreserve(&so->so_rcv, rcvcc) == 0)
57*4951Swnj 		goto bad2;
58*4951Swnj 	inp = mtod(m, struct inpcb *);
59*4951Swnj 	inp->inp_laddr = ifp->if_addr;
60*4951Swnj 	if (lport)
61*4951Swnj 		goto gotport;
62*4951Swnj again:
63*4951Swnj 	if (head->inp_lport++ < 1024)
64*4951Swnj 		head->inp_lport = 1024;
65*4951Swnj 	for (inp = head->inp_next; inp != head; inp = inp->inp_next)
66*4951Swnj 		if (inp->inp_lport == head->inp_lport)
67*4951Swnj 			goto again;
68*4951Swnj 	lport = head->inp_lport;
69*4951Swnj gotport:
70*4951Swnj 	inp->inp_lport = lport;
71*4951Swnj 	insque(head, inp);
72*4951Swnj 	so->so_pcb = (caddr_t)inp;
73*4951Swnj 	return (0);
74*4951Swnj bad2:
75*4951Swnj 	sbrelease(&so->so_snd);
76*4951Swnj bad:
77*4951Swnj 	m_free(m);
78*4951Swnj 	return (ENOBUFS);
794905Swnj }
804905Swnj 
81*4951Swnj in_pcbsetpeer(inp, sin)
82*4951Swnj 	struct inpcb *inp;
83*4951Swnj 	struct sockaddr_in *sin;
844923Swnj {
854923Swnj 
86*4951Swnj 	if (sin->sin_family != AF_INET)
87*4951Swnj 		return (EAFNOSUPPORT);
88*4951Swnj 	if (sin->sin_addr.s_addr == 0 || sin->sin_port == 0)
89*4951Swnj 		return (EADDRNOTAVAIL);
90*4951Swnj 	/* should check not already in use... */
91*4951Swnj 	inp->inp_faddr = sin->sin_addr;
92*4951Swnj 	inp->inp_fport = sin->sin_port;
934923Swnj 	return (0);
944923Swnj }
954923Swnj 
964905Swnj in_pcbfree(inp)
974905Swnj 	struct inpcb *inp;
984905Swnj {
994905Swnj 	struct socket *so = inp->inp_socket;
1004905Swnj 
101*4951Swnj 	if (so->so_state & SS_USERGONE)
1024905Swnj 		sofree(so);
1034905Swnj 	else
1044905Swnj 		so->so_pcb = 0;
1054907Swnj 	(void) m_free(dtom(inp));
1064905Swnj }
1074905Swnj 
1084907Swnj struct inpcb *
109*4951Swnj in_pcblookup(head, faddr, fport, laddr, lport)
1104905Swnj 	struct inpcb *head;
111*4951Swnj 	struct in_addr faddr, laddr;
1124905Swnj 	u_short fport, lport;
1134905Swnj {
1144905Swnj 	register struct inpcb *inp;
1154905Swnj 
1164907Swnj 	for (inp = head->inp_next; inp != head; inp = inp->inp_next)
117*4951Swnj 		if (inp->inp_faddr.s_addr == faddr.s_addr &&
1184905Swnj 		    inp->inp_fport == fport &&
119*4951Swnj 		    inp->inp_laddr.s_addr == laddr.s_addr &&
1204905Swnj 		    inp->inp_lport == lport)
1214905Swnj 			return (inp);
1224907Swnj 	for (inp = head->inp_next; inp != head; inp = inp->inp_next)
123*4951Swnj 		if ((inp->inp_faddr.s_addr == faddr.s_addr ||
124*4951Swnj 		     inp->inp_faddr.s_addr == 0) &&
1254905Swnj 		    (inp->inp_fport == fport || inp->inp_fport == 0) &&
126*4951Swnj 		     inp->inp_laddr.s_addr == laddr.s_addr &&
1274905Swnj 		    (inp->inp_lport == lport || inp->inp_lport == 0))
1284905Swnj 			return (inp);
1294905Swnj 	return (0);
1304905Swnj }
131