typo
[unix-history] / usr / src / sys / net / raw_cb.c
CommitLineData
ee787340 1/* raw_cb.c 4.6 82/03/28 */
785d93ac
BJ
2
3#include "../h/param.h"
4#include "../h/systm.h"
5#include "../h/mbuf.h"
6#include "../h/socket.h"
7#include "../h/socketvar.h"
8#include "../h/mtpr.h"
9#include "../net/in.h"
10#include "../net/in_systm.h"
11#include "../net/if.h"
12#include "../net/raw_cb.h"
ee787340 13#include "../net/pup.h"
1e25d807 14#include "../errno.h"
785d93ac
BJ
15
16/*
17 * Routines to manage the raw protocol control blocks.
18 *
19 * TODO:
20 * hash lookups by protocol family/protocol + address family
ee787340 21 * take care of unique address problems per AF?
1e25d807 22 * redo address binding to allow wildcards
785d93ac
BJ
23 */
24
25/*
26 * Allocate a control block and a nominal amount
27 * of buffer space for the socket.
28 */
29raw_attach(so, addr)
30 register struct socket *so;
31 struct sockaddr *addr;
32{
33 struct mbuf *m;
34 register struct rawcb *rp;
785d93ac
BJ
35
36COUNT(RAW_ATTACH);
ee787340
SL
37 if (ifnet == 0)
38 return (EADDRNOTAVAIL);
785d93ac
BJ
39 /*
40 * Should we verify address not already in use?
41 * Some say yes, others no.
42 */
43 if (addr) switch (addr->sa_family) {
44
a2cd4df7 45 case AF_IMPLINK:
ee787340
SL
46 case AF_INET:
47 if (((struct sockaddr_in *)addr)->sin_addr.s_addr &&
48 if_ifwithaddr(addr) == 0)
49 return (EADDRNOTAVAIL);
785d93ac 50 break;
785d93ac 51
ee787340
SL
52#ifdef PUP
53 /*
54 * Curious, we convert PUP address format to internet
55 * to allow us to verify we're asking for an Ethernet
56 * interface. This is wrong, but things are heavily
57 * oriented towards the internet addressing scheme, and
58 * converting internet to PUP would be very expensive.
59 */
60 case AF_PUP: {
61 struct sockaddr_pup *spup = (struct sockaddr_pup *)addr;
62 struct sockaddr_in inpup;
63
64 bzero((caddr_t)&inpup, sizeof(inpup));
65 inpup.sin_addr.s_net = spup->sp_net;
66 inpup.sin_addr.s_impno = spup->sp_host;
67 if (inpup.sin_addr.s_addr &&
68 if_ifwithaddr((struct sockaddr *)&inpup) == 0)
69 return (EADDRNOTAVAIL);
1e25d807 70 break;
ee787340
SL
71 }
72#endif
1e25d807 73
785d93ac
BJ
74 default:
75 return (EAFNOSUPPORT);
76 }
785d93ac
BJ
77 m = m_getclr(M_DONTWAIT);
78 if (m == 0)
79 return (ENOBUFS);
80 if (sbreserve(&so->so_snd, RAWSNDQ) == 0)
81 goto bad;
82 if (sbreserve(&so->so_rcv, RAWRCVQ) == 0)
83 goto bad2;
84 rp = mtod(m, struct rawcb *);
85 rp->rcb_socket = so;
86 insque(rp, &rawcb);
87 so->so_pcb = (caddr_t)rp;
88 rp->rcb_pcb = 0;
785d93ac 89 if (addr)
668cc26d 90 bcopy((caddr_t)addr, (caddr_t)&so->so_addr, sizeof(*addr));
785d93ac
BJ
91 return (0);
92bad2:
93 sbrelease(&so->so_snd);
94bad:
95 (void) m_free(m);
96 return (ENOBUFS);
97}
98
99/*
100 * Detach the raw connection block and discard
101 * socket resources.
102 */
103raw_detach(rp)
104 register struct rawcb *rp;
105{
106 struct socket *so = rp->rcb_socket;
107
108COUNT(RAW_DETACH);
785d93ac
BJ
109 so->so_pcb = 0;
110 sofree(so);
111 remque(rp);
ee787340 112 (void) m_freem(dtom(rp));
785d93ac
BJ
113}
114
115/*
116 * Disconnect and possibly release resources.
117 */
118raw_disconnect(rp)
119 struct rawcb *rp;
120{
121COUNT(RAW_DISCONNECT);
785d93ac
BJ
122 rp->rcb_flags &= ~RAW_ADDR;
123 if (rp->rcb_socket->so_state & SS_USERGONE)
124 raw_detach(rp);
125}
126
127/*
128 * Associate a peer's address with a
129 * raw connection block.
130 */
131raw_connaddr(rp, addr)
132 struct rawcb *rp;
133 struct sockaddr *addr;
134{
135COUNT(RAW_CONNADDR);
ee787340 136 bcopy((caddr_t)addr, (caddr_t)&rp->rcb_addr, sizeof(*addr));
785d93ac
BJ
137 rp->rcb_flags |= RAW_ADDR;
138}