1 /*
2 * Copyright (c) 2004 Robert N. M. Watson
3 * Copyright (c) 1990,1994 Regents of The University of Michigan.
4 * All Rights Reserved. See COPYRIGHT.
5 *
6 * $FreeBSD: releng/5.3/sys/netatalk/ddp_usrreq.c 136588 2004-10-16 08:43:07Z cvs2svn $
7 */
8
9 #include <sys/param.h>
10 #include <sys/systm.h>
11 #include <sys/malloc.h>
12 #include <sys/mbuf.h>
13 #include <sys/socket.h>
14 #include <sys/socketvar.h>
15 #include <sys/protosw.h>
16 #include <net/if.h>
17 #include <net/route.h>
18 #include <net/netisr.h>
19
20 #include <netatalk/at.h>
21 #include <netatalk/at_var.h>
22 #include <netatalk/ddp_var.h>
23 #include <netatalk/ddp_pcb.h>
24 #include <netatalk/at_extern.h>
25
26 static u_long ddp_sendspace = DDP_MAXSZ; /* Max ddp size + 1 (ddp_type) */
27 static u_long ddp_recvspace = 10 * (587 + sizeof(struct sockaddr_at));
28
29 static struct ifqueue atintrq1, atintrq2, aarpintrq;
30
31 static int
32 ddp_attach(struct socket *so, int proto, struct thread *td)
33 {
34 struct ddpcb *ddp;
35 int error = 0;
36
37 ddp = sotoddpcb(so);
38 if (ddp != NULL)
39 return (EINVAL);
40
41 /*
42 * Allocate socket buffer space first so that it's present
43 * before first use.
44 */
45 error = soreserve(so, ddp_sendspace, ddp_recvspace);
46 if (error)
47 return (error);
48
49 DDP_LIST_XLOCK();
50 error = at_pcballoc(so);
51 DDP_LIST_XUNLOCK();
52 return (error);
53 }
54
55 static int
56 ddp_detach(struct socket *so)
57 {
58 struct ddpcb *ddp;
59
60 ddp = sotoddpcb(so);
61 if (ddp == NULL)
62 return (EINVAL);
63
64 DDP_LIST_XLOCK();
65 DDP_LOCK(ddp);
66 at_pcbdetach(so, ddp);
67 DDP_LIST_XUNLOCK();
68 return (0);
69 }
70
71 static int
72 ddp_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
73 {
74 struct ddpcb *ddp;
75 int error = 0;
76
77 ddp = sotoddpcb(so);
78 if (ddp == NULL) {
79 return (EINVAL);
80 }
81 DDP_LIST_XLOCK();
82 DDP_LOCK(ddp);
83 error = at_pcbsetaddr(ddp, nam, td);
84 DDP_UNLOCK(ddp);
85 DDP_LIST_XUNLOCK();
86 return (error);
87 }
88
89 static int
90 ddp_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
91 {
92 struct ddpcb *ddp;
93 int error = 0;
94
95 ddp = sotoddpcb(so);
96 if (ddp == NULL) {
97 return (EINVAL);
98 }
99
100 DDP_LIST_XLOCK();
101 DDP_LOCK(ddp);
102 if (ddp->ddp_fsat.sat_port != ATADDR_ANYPORT) {
103 DDP_UNLOCK(ddp);
104 DDP_LIST_XUNLOCK();
105 return (EISCONN);
106 }
107
108 error = at_pcbconnect( ddp, nam, td );
109 DDP_UNLOCK(ddp);
110 DDP_LIST_XUNLOCK();
111 if (error == 0)
112 soisconnected(so);
113 return (error);
114 }
115
116 static int
117 ddp_disconnect(struct socket *so)
118 {
119
120 struct ddpcb *ddp;
121
122 ddp = sotoddpcb(so);
123 if (ddp == NULL) {
124 return (EINVAL);
125 }
126 DDP_LOCK(ddp);
127 if (ddp->ddp_fsat.sat_addr.s_node == ATADDR_ANYNODE) {
128 DDP_UNLOCK(ddp);
129 return (ENOTCONN);
130 }
131
132 at_pcbdisconnect(ddp);
133 ddp->ddp_fsat.sat_addr.s_node = ATADDR_ANYNODE;
134 DDP_UNLOCK(ddp);
135 soisdisconnected(so);
136 return (0);
137 }
138
139 static int
140 ddp_shutdown(struct socket *so)
141 {
142 struct ddpcb *ddp;
143
144 ddp = sotoddpcb(so);
145 if (ddp == NULL) {
146 return (EINVAL);
147 }
148 socantsendmore(so);
149 return (0);
150 }
151
152 static int
153 ddp_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
154 struct mbuf *control, struct thread *td)
155 {
156 struct ddpcb *ddp;
157 int error = 0;
158
159 ddp = sotoddpcb(so);
160 if (ddp == NULL) {
161 return (EINVAL);
162 }
163
164 if (control && control->m_len) {
165 return (EINVAL);
166 }
167
168 if (addr != NULL) {
169 DDP_LIST_XLOCK();
170 DDP_LOCK(ddp);
171 if (ddp->ddp_fsat.sat_port != ATADDR_ANYPORT) {
172 error = EISCONN;
173 goto out;
174 }
175
176 error = at_pcbconnect(ddp, addr, td);
177 if (error == 0) {
178 error = ddp_output(m, so);
179 at_pcbdisconnect(ddp);
180 }
181 out:
182 DDP_UNLOCK(ddp);
183 DDP_LIST_XUNLOCK();
184 } else {
185 DDP_LOCK(ddp);
186 if (ddp->ddp_fsat.sat_port == ATADDR_ANYPORT)
187 error = ENOTCONN;
188 else
189 error = ddp_output(m, so);
190 DDP_UNLOCK(ddp);
191 }
192 return (error);
193 }
194
195 static int
196 ddp_abort(struct socket *so)
197 {
198 struct ddpcb *ddp;
199
200 ddp = sotoddpcb(so);
201 if (ddp == NULL) {
202 return (EINVAL);
203 }
204 DDP_LIST_XLOCK();
205 DDP_LOCK(ddp);
206 at_pcbdetach(so, ddp);
207 DDP_LIST_XUNLOCK();
208 return (0);
209 }
210
211 void
212 ddp_init(void)
213 {
214 atintrq1.ifq_maxlen = IFQ_MAXLEN;
215 atintrq2.ifq_maxlen = IFQ_MAXLEN;
216 aarpintrq.ifq_maxlen = IFQ_MAXLEN;
217 mtx_init(&atintrq1.ifq_mtx, "at1_inq", NULL, MTX_DEF);
218 mtx_init(&atintrq2.ifq_mtx, "at2_inq", NULL, MTX_DEF);
219 mtx_init(&aarpintrq.ifq_mtx, "aarp_inq", NULL, MTX_DEF);
220 DDP_LIST_LOCK_INIT();
221 netisr_register(NETISR_ATALK1, at1intr, &atintrq1, 0);
222 netisr_register(NETISR_ATALK2, at2intr, &atintrq2, 0);
223 netisr_register(NETISR_AARP, aarpintr, &aarpintrq, 0);
224 }
225
226 #if 0
227 static void
228 ddp_clean(void)
229 {
230 struct ddpcb *ddp;
231
232 for (ddp = ddpcb_list; ddp != NULL; ddp = ddp->ddp_next) {
233 at_pcbdetach(ddp->ddp_socket, ddp);
234 }
235 DDP_LIST_LOCK_DESTROY();
236 }
237 #endif
238
239 static int
240 at_setpeeraddr(struct socket *so, struct sockaddr **nam)
241 {
242 return (EOPNOTSUPP);
243 }
244
245 static int
246 at_setsockaddr(struct socket *so, struct sockaddr **nam)
247 {
248 struct ddpcb *ddp;
249
250 ddp = sotoddpcb(so);
251 if (ddp == NULL) {
252 return (EINVAL);
253 }
254 DDP_LOCK(ddp);
255 at_sockaddr(ddp, nam);
256 DDP_UNLOCK(ddp);
257 return (0);
258 }
259
260 struct pr_usrreqs ddp_usrreqs = {
261 ddp_abort,
262 pru_accept_notsupp,
263 ddp_attach,
264 ddp_bind,
265 ddp_connect,
266 pru_connect2_notsupp,
267 at_control,
268 ddp_detach,
269 ddp_disconnect,
270 pru_listen_notsupp,
271 at_setpeeraddr,
272 pru_rcvd_notsupp,
273 pru_rcvoob_notsupp,
274 ddp_send,
275 pru_sense_null,
276 ddp_shutdown,
277 at_setsockaddr,
278 sosend,
279 soreceive,
280 sopoll,
281 pru_sosetlabel_null
282 };
Cache object: 2759e9317e9a89d15976a9268c84e863
|