no flipping of sport/dport
[unix-history] / usr / src / sys / netinet / in_pcb.c
CommitLineData
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 */
20in_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;
62again:
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;
69gotport:
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);
79bad2:
80 sbrelease(&so->so_snd);
81bad:
2752c877 82 (void) m_free(m);
4ad99bae 83 return (ENOBUFS);
af092e86
BJ
84}
85
4ad99bae
BJ
86in_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
101in_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 112struct inpcb *
4ad99bae 113in_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}