Commit | Line | Data |
---|---|---|
ba55c9af | 1 | /* in_pcb.c 4.8 81/11/21 */ |
af092e86 BJ |
2 | |
3 | #include "../h/param.h" | |
4ad99bae BJ |
4 | #include "../h/systm.h" |
5 | #include "../h/dir.h" | |
6 | #include "../h/user.h" | |
af092e86 BJ |
7 | #include "../h/mbuf.h" |
8 | #include "../h/socket.h" | |
9 | #include "../h/socketvar.h" | |
10 | #include "../net/inet.h" | |
11 | #include "../net/inet_systm.h" | |
4ad99bae | 12 | #include "../net/if.h" |
cdad2eb1 | 13 | #include "../net/inet_pcb.h" |
af092e86 | 14 | |
4ad99bae BJ |
15 | /* |
16 | * Allocate a protocol control block, space | |
17 | * for send and receive data, and local host information. | |
18 | * Return error. If no error make socket point at pcb. | |
19 | */ | |
20 | in_pcballoc(so, head, sndcc, rcvcc, sin) | |
21 | struct socket *so; | |
22 | struct inpcb *head; | |
23 | int sndcc, rcvcc; | |
24 | struct sockaddr_in *sin; | |
af092e86 | 25 | { |
af092e86 | 26 | struct mbuf *m; |
7545cf09 | 27 | register struct inpcb *inp, *xp; |
4ad99bae BJ |
28 | struct ifnet *ifp; |
29 | u_long lport; | |
af092e86 | 30 | |
4ad99bae BJ |
31 | if (sin) { |
32 | if (sin->sin_family != AF_INET) | |
33 | return (EAFNOSUPPORT); | |
34 | ifp = if_ifwithaddr(sin->sin_addr); | |
35 | if (ifp == 0) | |
36 | return (EADDRNOTAVAIL); | |
37 | lport = sin->sin_port; | |
38 | if (lport) { | |
7545cf09 BJ |
39 | xp = head->inp_next; |
40 | for (; xp != head; xp = inp->inp_next) | |
41 | if (xp->inp_laddr.s_addr == | |
4ad99bae | 42 | sin->sin_addr.s_addr && |
7545cf09 BJ |
43 | xp->inp_lport == lport && |
44 | xp->inp_faddr.s_addr == 0) | |
4ad99bae BJ |
45 | return (EADDRINUSE); |
46 | } | |
47 | } else { | |
48 | ifp = if_ifwithaddr(ifnet->if_addr); | |
49 | lport = 0; | |
50 | } | |
af092e86 | 51 | m = m_getclr(M_WAIT); |
4ad99bae | 52 | if (m == 0) |
7545cf09 | 53 | return (ENOBUFS); |
4ad99bae BJ |
54 | if (sbreserve(&so->so_snd, sndcc) == 0) |
55 | goto bad; | |
56 | if (sbreserve(&so->so_rcv, rcvcc) == 0) | |
57 | goto bad2; | |
58 | inp = mtod(m, struct inpcb *); | |
59 | inp->inp_laddr = ifp->if_addr; | |
60 | if (lport) | |
61 | goto gotport; | |
62 | again: | |
63 | if (head->inp_lport++ < 1024) | |
64 | head->inp_lport = 1024; | |
7545cf09 BJ |
65 | for (xp = head->inp_next; xp != head; xp = xp->inp_next) |
66 | if (xp->inp_lport == head->inp_lport) | |
4ad99bae BJ |
67 | goto again; |
68 | lport = head->inp_lport; | |
69 | gotport: | |
7545cf09 | 70 | inp->inp_socket = so; |
4ad99bae | 71 | inp->inp_lport = lport; |
7545cf09 | 72 | insque(inp, head); |
4ad99bae | 73 | so->so_pcb = (caddr_t)inp; |
d8bd11cd BJ |
74 | sin = (struct sockaddr_in *)&so->so_addr; |
75 | sin->sin_family = AF_INET; | |
76 | sin->sin_addr = inp->inp_laddr; | |
77 | sin->sin_port = inp->inp_lport; | |
4ad99bae BJ |
78 | return (0); |
79 | bad2: | |
80 | sbrelease(&so->so_snd); | |
81 | bad: | |
2752c877 | 82 | (void) m_free(m); |
4ad99bae | 83 | return (ENOBUFS); |
af092e86 BJ |
84 | } |
85 | ||
4ad99bae BJ |
86 | in_pcbsetpeer(inp, sin) |
87 | struct inpcb *inp; | |
88 | struct sockaddr_in *sin; | |
2b4b57cd | 89 | { |
2b4b57cd | 90 | |
4ad99bae BJ |
91 | if (sin->sin_family != AF_INET) |
92 | return (EAFNOSUPPORT); | |
93 | if (sin->sin_addr.s_addr == 0 || sin->sin_port == 0) | |
94 | return (EADDRNOTAVAIL); | |
95 | /* should check not already in use... */ | |
96 | inp->inp_faddr = sin->sin_addr; | |
97 | inp->inp_fport = sin->sin_port; | |
2b4b57cd BJ |
98 | return (0); |
99 | } | |
100 | ||
af092e86 BJ |
101 | in_pcbfree(inp) |
102 | struct inpcb *inp; | |
103 | { | |
104 | struct socket *so = inp->inp_socket; | |
105 | ||
ba55c9af BJ |
106 | so->so_pcb = 0; |
107 | sofree(so); | |
7545cf09 | 108 | remque(inp); |
cdad2eb1 | 109 | (void) m_free(dtom(inp)); |
af092e86 BJ |
110 | } |
111 | ||
cdad2eb1 | 112 | struct inpcb * |
4ad99bae | 113 | in_pcblookup(head, faddr, fport, laddr, lport) |
af092e86 | 114 | struct inpcb *head; |
4ad99bae | 115 | struct in_addr faddr, laddr; |
af092e86 BJ |
116 | u_short fport, lport; |
117 | { | |
118 | register struct inpcb *inp; | |
119 | ||
cdad2eb1 | 120 | for (inp = head->inp_next; inp != head; inp = inp->inp_next) |
4ad99bae | 121 | if (inp->inp_faddr.s_addr == faddr.s_addr && |
af092e86 | 122 | inp->inp_fport == fport && |
4ad99bae | 123 | inp->inp_laddr.s_addr == laddr.s_addr && |
af092e86 BJ |
124 | inp->inp_lport == lport) |
125 | return (inp); | |
cdad2eb1 | 126 | for (inp = head->inp_next; inp != head; inp = inp->inp_next) |
4ad99bae BJ |
127 | if ((inp->inp_faddr.s_addr == faddr.s_addr || |
128 | inp->inp_faddr.s_addr == 0) && | |
af092e86 | 129 | (inp->inp_fport == fport || inp->inp_fport == 0) && |
4ad99bae | 130 | inp->inp_laddr.s_addr == laddr.s_addr && |
af092e86 BJ |
131 | (inp->inp_lport == lport || inp->inp_lport == 0)) |
132 | return (inp); | |
133 | return (0); | |
134 | } |