]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/netatalk/ddp_usrreq.c
This commit was generated by cvs2svn to compensate for changes in r157191,
[FreeBSD/FreeBSD.git] / sys / netatalk / ddp_usrreq.c
1 /*-
2  * Copyright (c) 2004-2005 Robert N. M. Watson
3  * Copyright (c) 1990,1994 Regents of The University of Michigan.
4  * All Rights Reserved.
5  *
6  * Permission to use, copy, modify, and distribute this software and
7  * its documentation for any purpose and without fee is hereby granted,
8  * provided that the above copyright notice appears in all copies and
9  * that both that copyright notice and this permission notice appear
10  * in supporting documentation, and that the name of The University
11  * of Michigan not be used in advertising or publicity pertaining to
12  * distribution of the software without specific, written prior
13  * permission. This software is supplied as is without expressed or
14  * implied warranties of any kind.
15  *
16  * This product includes software developed by the University of
17  * California, Berkeley and its contributors.
18  *
19  *      Research Systems Unix Group
20  *      The University of Michigan
21  *      c/o Wesley Craig
22  *      535 W. William Street
23  *      Ann Arbor, Michigan
24  *      +1-313-764-2278
25  *      netatalk@umich.edu
26  *
27  * $FreeBSD$
28  */
29
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/malloc.h>
33 #include <sys/mbuf.h>
34 #include <sys/socket.h>
35 #include <sys/socketvar.h>
36 #include <sys/protosw.h>
37 #include <net/if.h>
38 #include <net/route.h>
39 #include <net/netisr.h>
40
41 #include <netatalk/at.h>
42 #include <netatalk/at_var.h>
43 #include <netatalk/ddp_var.h>
44 #include <netatalk/ddp_pcb.h>
45 #include <netatalk/at_extern.h>
46
47 static u_long   ddp_sendspace = DDP_MAXSZ; /* Max ddp size + 1 (ddp_type) */
48 static u_long   ddp_recvspace = 10 * (587 + sizeof(struct sockaddr_at));
49
50 static struct ifqueue atintrq1, atintrq2, aarpintrq;
51
52 static int
53 ddp_attach(struct socket *so, int proto, struct thread *td)
54 {
55         struct ddpcb    *ddp;
56         int             error = 0;
57         
58         ddp = sotoddpcb(so);
59         KASSERT(ddp == NULL, ("ddp_attach: ddp != NULL"));
60
61         /*
62          * Allocate socket buffer space first so that it's present
63          * before first use.
64          */
65         error = soreserve(so, ddp_sendspace, ddp_recvspace);
66         if (error)
67                 return (error);
68
69         DDP_LIST_XLOCK();
70         error = at_pcballoc(so);
71         DDP_LIST_XUNLOCK();
72         return (error);
73 }
74
75 static int
76 ddp_detach(struct socket *so)
77 {
78         struct ddpcb    *ddp;
79         
80         ddp = sotoddpcb(so);
81         KASSERT(ddp != NULL, ("ddp_detach: ddp == NULL"));
82
83         DDP_LIST_XLOCK();
84         DDP_LOCK(ddp);
85         at_pcbdetach(so, ddp);
86         DDP_LIST_XUNLOCK();
87         return (0);
88 }
89
90 static int      
91 ddp_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
92 {
93         struct ddpcb    *ddp;
94         int             error = 0;
95         
96         ddp = sotoddpcb(so);
97         KASSERT(ddp != NULL, ("ddp_bind: ddp == NULL"));
98         DDP_LIST_XLOCK();
99         DDP_LOCK(ddp);
100         error = at_pcbsetaddr(ddp, nam, td);
101         DDP_UNLOCK(ddp);
102         DDP_LIST_XUNLOCK();
103         return (error);
104 }
105     
106 static int
107 ddp_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
108 {
109         struct ddpcb    *ddp;
110         int             error = 0;
111         
112         ddp = sotoddpcb(so);
113         KASSERT(ddp != NULL, ("ddp_connect: ddp == NULL"));
114         DDP_LIST_XLOCK();
115         DDP_LOCK(ddp);
116         if (ddp->ddp_fsat.sat_port != ATADDR_ANYPORT) {
117             DDP_UNLOCK(ddp);
118             DDP_LIST_XUNLOCK();
119             return (EISCONN);
120         }
121
122         error = at_pcbconnect( ddp, nam, td );
123         DDP_UNLOCK(ddp);
124         DDP_LIST_XUNLOCK();
125         if (error == 0)
126             soisconnected(so);
127         return (error);
128 }
129
130 static int
131 ddp_disconnect(struct socket *so)
132 {
133
134         struct ddpcb    *ddp;
135         
136         ddp = sotoddpcb(so);
137         KASSERT(ddp != NULL, ("ddp_disconnect: ddp == NULL"));
138         DDP_LOCK(ddp);
139         if (ddp->ddp_fsat.sat_addr.s_node == ATADDR_ANYNODE) {
140             DDP_UNLOCK(ddp);
141             return (ENOTCONN);
142         }
143
144         at_pcbdisconnect(ddp);
145         ddp->ddp_fsat.sat_addr.s_node = ATADDR_ANYNODE;
146         DDP_UNLOCK(ddp);
147         soisdisconnected(so);
148         return (0);
149 }
150
151 static int
152 ddp_shutdown(struct socket *so)
153 {
154         struct ddpcb    *ddp;
155
156         ddp = sotoddpcb(so);
157         KASSERT(ddp != NULL, ("ddp_shutdown: ddp == NULL"));
158         socantsendmore(so);
159         return (0);
160 }
161
162 static int
163 ddp_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
164             struct mbuf *control, struct thread *td)
165 {
166         struct ddpcb    *ddp;
167         int             error = 0;
168         
169         ddp = sotoddpcb(so);
170         KASSERT(ddp != NULL, ("ddp_send: ddp == NULL"));
171
172         if (control && control->m_len) {
173                 return (EINVAL);
174         }
175
176         if (addr != NULL) {
177                 DDP_LIST_XLOCK();
178                 DDP_LOCK(ddp);
179                 if (ddp->ddp_fsat.sat_port != ATADDR_ANYPORT) {
180                         error = EISCONN;
181                         goto out;
182                 }
183
184                 error = at_pcbconnect(ddp, addr, td);
185                 if (error == 0) {
186                         error = ddp_output(m, so);
187                         at_pcbdisconnect(ddp);
188                 }
189 out:
190                 DDP_UNLOCK(ddp);
191                 DDP_LIST_XUNLOCK();
192         } else {
193                 DDP_LOCK(ddp);
194                 if (ddp->ddp_fsat.sat_port == ATADDR_ANYPORT)
195                         error = ENOTCONN;
196                 else
197                         error = ddp_output(m, so);
198                 DDP_UNLOCK(ddp);
199         }
200         return (error);
201 }
202
203 static int
204 ddp_abort(struct socket *so)
205 {
206         struct ddpcb    *ddp;
207         
208         ddp = sotoddpcb(so);
209         KASSERT(ddp != NULL, ("ddp_abort: ddp == NULL"));
210         DDP_LIST_XLOCK();
211         DDP_LOCK(ddp);
212         at_pcbdetach(so, ddp);
213         DDP_LIST_XUNLOCK();
214         /* XXXRW: Should be calling sotryfree() here? */
215         return (0);
216 }
217
218 void 
219 ddp_init(void)
220 {
221         atintrq1.ifq_maxlen = IFQ_MAXLEN;
222         atintrq2.ifq_maxlen = IFQ_MAXLEN;
223         aarpintrq.ifq_maxlen = IFQ_MAXLEN;
224         mtx_init(&atintrq1.ifq_mtx, "at1_inq", NULL, MTX_DEF);
225         mtx_init(&atintrq2.ifq_mtx, "at2_inq", NULL, MTX_DEF);
226         mtx_init(&aarpintrq.ifq_mtx, "aarp_inq", NULL, MTX_DEF);
227         DDP_LIST_LOCK_INIT();
228         netisr_register(NETISR_ATALK1, at1intr, &atintrq1, NETISR_MPSAFE);
229         netisr_register(NETISR_ATALK2, at2intr, &atintrq2, NETISR_MPSAFE);
230         netisr_register(NETISR_AARP, aarpintr, &aarpintrq, NETISR_MPSAFE);
231 }
232
233 #if 0
234 static void 
235 ddp_clean(void)
236 {
237     struct ddpcb        *ddp;
238
239     for (ddp = ddpcb_list; ddp != NULL; ddp = ddp->ddp_next) {
240         at_pcbdetach(ddp->ddp_socket, ddp);
241     }
242     DDP_LIST_LOCK_DESTROY();
243 }
244 #endif
245
246 static int
247 at_setpeeraddr(struct socket *so, struct sockaddr **nam)
248 {
249         return (EOPNOTSUPP);
250 }
251
252 static int
253 at_setsockaddr(struct socket *so, struct sockaddr **nam)
254 {
255         struct ddpcb    *ddp;
256
257         ddp = sotoddpcb(so);
258         KASSERT(ddp != NULL, ("at_setsockaddr: ddp == NULL"));
259
260         DDP_LOCK(ddp);
261         at_sockaddr(ddp, nam);
262         DDP_UNLOCK(ddp);
263         return (0);
264 }
265
266 struct pr_usrreqs ddp_usrreqs = {
267         .pru_abort =            ddp_abort,
268         .pru_attach =           ddp_attach,
269         .pru_bind =             ddp_bind,
270         .pru_connect =          ddp_connect,
271         .pru_control =          at_control,
272         .pru_detach =           ddp_detach,
273         .pru_disconnect =       ddp_disconnect,
274         .pru_peeraddr =         at_setpeeraddr,
275         .pru_send =             ddp_send,
276         .pru_shutdown =         ddp_shutdown,
277         .pru_sockaddr =         at_setsockaddr,
278 };