|
|
1.1 root 1: /* in_pcb.c 6.1 83/07/29 */
2:
3: #include "../h/param.h"
4: #include "../h/systm.h"
5: #include "../h/dir.h"
6: #include "../h/user.h"
7: #include "../h/mbuf.h"
8: #include "../h/socket.h"
9: #include "../h/socketvar.h"
10: #include "../netinet/in.h"
11: #include "../netinet/in_systm.h"
12: #include "../net/if.h"
13: #include "../net/route.h"
14: #include "../netinet/in_pcb.h"
15: #include "../h/protosw.h"
16:
17: struct in_addr zeroin_addr;
18:
19: in_pcballoc(so, head)
20: struct socket *so;
21: struct inpcb *head;
22: {
23: struct mbuf *m;
24: register struct inpcb *inp;
25:
26: m = m_getclr(M_DONTWAIT, MT_PCB);
27: MBUFNULL(45, m); /* for debugging */
28: if (m == NULL)
29: return (ENOBUFS);
30: inp = mtod(m, struct inpcb *);
31: inp->inp_head = head;
32: inp->inp_socket = so;
33: insque(inp, head);
34: so->so_pcb = (caddr_t)inp;
35: return (0);
36: }
37:
38: in_pcbbind(inp, nam)
39: register struct inpcb *inp;
40: struct mbuf *nam;
41: {
42: register struct socket *so = inp->inp_socket;
43: register struct inpcb *head = inp->inp_head;
44: register struct sockaddr_in *sin;
45: u_short lport = 0;
46:
47: if (ifnet == 0)
48: return (EADDRNOTAVAIL);
49: if (inp->inp_lport || inp->inp_laddr.s_addr != INADDR_ANY)
50: return (EINVAL);
51: if (nam == 0)
52: goto noname;
53: sin = mtod(nam, struct sockaddr_in *);
54: if (nam->m_len != sizeof (*sin))
55: return (EINVAL);
56: if (sin->sin_addr.s_addr != INADDR_ANY) {
57: int tport = sin->sin_port;
58:
59: sin->sin_port = 0; /* yech... */
60: if (if_ifwithaddr((struct sockaddr *)sin) == 0)
61: return (EADDRNOTAVAIL);
62: sin->sin_port = tport;
63: }
64: lport = sin->sin_port;
65: if (lport) {
66: u_short aport = ntohs(lport);
67: int wild = 0;
68:
69: /* GROSS */
70: if (aport < IPPORT_RESERVED && u.u_uid != 0)
71: return (EACCES);
72: /* even GROSSER, but this is the Internet */
73: if ((so->so_options & SO_REUSEADDR) == 0 &&
74: ((so->so_proto->pr_flags & PR_CONNREQUIRED) == 0 ||
75: (so->so_options & SO_ACCEPTCONN) == 0))
76: wild = INPLOOKUP_WILDCARD;
77: if (in_pcblookup(head,
78: zeroin_addr, 0, sin->sin_addr, lport, wild))
79: return (EADDRINUSE);
80: }
81: inp->inp_laddr = sin->sin_addr;
82: noname:
83: if (lport == 0)
84: do {
85: if (head->inp_lport++ < IPPORT_RESERVED)
86: head->inp_lport = IPPORT_RESERVED;
87: lport = htons(head->inp_lport);
88: } while (in_pcblookup(head,
89: zeroin_addr, 0, inp->inp_laddr, lport, 0));
90: inp->inp_lport = lport;
91: return (0);
92: }
93:
94: /*
95: * Connect from a socket to a specified address.
96: * Both address and port must be specified in argument sin.
97: * If don't have a local address for this socket yet,
98: * then pick one.
99: */
100: in_pcbconnect(inp, nam)
101: struct inpcb *inp;
102: struct mbuf *nam;
103: {
104: struct ifnet *ifp;
105: struct sockaddr_in *ifaddr;
106: register struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
107:
108: if (nam->m_len != sizeof (*sin))
109: return (EINVAL);
110: if (sin->sin_family != AF_INET)
111: return (EAFNOSUPPORT);
112: if (sin->sin_addr.s_addr == INADDR_ANY || sin->sin_port == 0)
113: return (EADDRNOTAVAIL);
114: if (inp->inp_laddr.s_addr == INADDR_ANY) {
115: ifp = if_ifonnetof(in_netof(sin->sin_addr));
116: if (ifp == 0) {
117: /*
118: * We should select the interface based on
119: * the route to be used, but for udp this would
120: * result in two calls to rtalloc for each packet
121: * sent; hardly worthwhile...
122: */
123: ifp = if_ifwithaf(AF_INET);
124: if (ifp == 0)
125: return (EADDRNOTAVAIL);
126: }
127: ifaddr = (struct sockaddr_in *)&ifp->if_addr;
128: }
129: if (in_pcblookup(inp->inp_head,
130: sin->sin_addr,
131: sin->sin_port,
132: inp->inp_laddr.s_addr ? inp->inp_laddr : ifaddr->sin_addr,
133: inp->inp_lport,
134: 0))
135: return (EADDRINUSE);
136: if (inp->inp_laddr.s_addr == INADDR_ANY) {
137: if (inp->inp_lport == 0)
138: in_pcbbind(inp, (struct mbuf *)0);
139: inp->inp_laddr = ifaddr->sin_addr;
140: }
141: inp->inp_faddr = sin->sin_addr;
142: inp->inp_fport = sin->sin_port;
143: return (0);
144: }
145:
146: in_pcbdisconnect(inp)
147: struct inpcb *inp;
148: {
149:
150: inp->inp_faddr.s_addr = INADDR_ANY;
151: inp->inp_fport = 0;
152: if (inp->inp_socket->so_state & SS_NOFDREF)
153: in_pcbdetach(inp);
154: }
155:
156: in_pcbdetach(inp)
157: struct inpcb *inp;
158: {
159: struct socket *so = inp->inp_socket;
160:
161: so->so_pcb = 0;
162: sofree(so);
163: if (inp->inp_route.ro_rt)
164: rtfree(inp->inp_route.ro_rt);
165: remque(inp);
166: (void) m_free(dtom(inp));
167: }
168:
169: in_setsockaddr(inp, nam)
170: register struct inpcb *inp;
171: struct mbuf *nam;
172: {
173: register struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
174:
175: nam->m_len = sizeof (*sin);
176: sin = mtod(nam, struct sockaddr_in *);
177: bzero((caddr_t)sin, sizeof (*sin));
178: sin->sin_family = AF_INET;
179: sin->sin_port = inp->inp_lport;
180: sin->sin_addr = inp->inp_laddr;
181: }
182:
183: in_setpeeraddr(inp, nam)
184: register struct inpcb *inp;
185: struct mbuf *nam;
186: {
187: register struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
188:
189: nam->m_len = sizeof (*sin);
190: sin = mtod(nam, struct sockaddr_in *);
191: bzero((caddr_t)sin, sizeof (*sin));
192: sin->sin_family = AF_INET;
193: sin->sin_port = inp->inp_fport;
194: sin->sin_addr = inp->inp_faddr;
195: }
196:
197: /*
198: * Pass an error to all internet connections
199: * associated with address sin. Call the
200: * protocol specific routine to clean up the
201: * mess afterwards.
202: */
203: in_pcbnotify(head, dst, errno, abort)
204: struct inpcb *head;
205: register struct in_addr *dst;
206: int errno, (*abort)();
207: {
208: register struct inpcb *inp, *oinp;
209: int s = splimp();
210:
211: for (inp = head->inp_next; inp != head;) {
212: if (inp->inp_faddr.s_addr != dst->s_addr) {
213: next:
214: inp = inp->inp_next;
215: continue;
216: }
217: if (inp->inp_socket == 0)
218: goto next;
219: inp->inp_socket->so_error = errno;
220: oinp = inp;
221: inp = inp->inp_next;
222: (*abort)(oinp);
223: }
224: splx(s);
225: }
226:
227: struct inpcb *
228: in_pcblookup(head, faddr, fport, laddr, lport, flags)
229: struct inpcb *head;
230: struct in_addr faddr, laddr;
231: u_short fport, lport;
232: int flags;
233: {
234: register struct inpcb *inp, *match = 0;
235: int matchwild = 3, wildcard;
236:
237: for (inp = head->inp_next; inp != head; inp = inp->inp_next) {
238: if (inp->inp_lport != lport)
239: continue;
240: wildcard = 0;
241: if (inp->inp_laddr.s_addr != INADDR_ANY) {
242: if (laddr.s_addr == INADDR_ANY)
243: wildcard++;
244: else if (inp->inp_laddr.s_addr != laddr.s_addr)
245: continue;
246: } else {
247: if (laddr.s_addr != INADDR_ANY)
248: wildcard++;
249: }
250: if (inp->inp_faddr.s_addr != INADDR_ANY) {
251: if (faddr.s_addr == INADDR_ANY)
252: wildcard++;
253: else if (inp->inp_faddr.s_addr != faddr.s_addr ||
254: inp->inp_fport != fport)
255: continue;
256: } else {
257: if (faddr.s_addr != INADDR_ANY)
258: wildcard++;
259: }
260: if (wildcard && (flags & INPLOOKUP_WILDCARD) == 0)
261: continue;
262: if (wildcard < matchwild) {
263: match = inp;
264: matchwild = wildcard;
265: if (matchwild == 0)
266: break;
267: }
268: }
269: return (match);
270: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.