Deleted Added
full compact
ddp_usrreq.c (111119) ddp_usrreq.c (111888)
1/*
2 * Copyright (c) 1990,1994 Regents of The University of Michigan.
3 * All Rights Reserved. See COPYRIGHT.
4 *
1/*
2 * Copyright (c) 1990,1994 Regents of The University of Michigan.
3 * All Rights Reserved. See COPYRIGHT.
4 *
5 * $FreeBSD: head/sys/netatalk/ddp_usrreq.c 111119 2003-02-19 05:47:46Z imp $
5 * $FreeBSD: head/sys/netatalk/ddp_usrreq.c 111888 2003-03-04 23:19:55Z jlemon $
6 */
7
8#include <sys/param.h>
9#include <sys/systm.h>
10#include <sys/malloc.h>
11#include <sys/mbuf.h>
12#include <sys/socket.h>
13#include <sys/socketvar.h>
14#include <sys/protosw.h>
15#include <net/if.h>
16#include <net/route.h>
6 */
7
8#include <sys/param.h>
9#include <sys/systm.h>
10#include <sys/malloc.h>
11#include <sys/mbuf.h>
12#include <sys/socket.h>
13#include <sys/socketvar.h>
14#include <sys/protosw.h>
15#include <net/if.h>
16#include <net/route.h>
17#include <net/intrq.h>
17#include <net/netisr.h>
18
19#include <netatalk/at.h>
20#include <netatalk/at_var.h>
21#include <netatalk/ddp_var.h>
22#include <netatalk/at_extern.h>
23
24static void at_pcbdisconnect( struct ddpcb *ddp );
25static void at_sockaddr(struct ddpcb *ddp, struct sockaddr **addr);
26static int at_pcbsetaddr(struct ddpcb *ddp, struct sockaddr *addr,
27 struct thread *td);
28static int at_pcbconnect(struct ddpcb *ddp, struct sockaddr *addr,
29 struct thread *td);
30static void at_pcbdetach(struct socket *so, struct ddpcb *ddp);
31static int at_pcballoc(struct socket *so);
32
33struct ddpcb *ddp_ports[ ATPORT_LAST ];
34struct ddpcb *ddpcb = NULL;
35static u_long ddp_sendspace = DDP_MAXSZ; /* Max ddp size + 1 (ddp_type) */
36static u_long ddp_recvspace = 10 * ( 587 + sizeof( struct sockaddr_at ));
37
18
19#include <netatalk/at.h>
20#include <netatalk/at_var.h>
21#include <netatalk/ddp_var.h>
22#include <netatalk/at_extern.h>
23
24static void at_pcbdisconnect( struct ddpcb *ddp );
25static void at_sockaddr(struct ddpcb *ddp, struct sockaddr **addr);
26static int at_pcbsetaddr(struct ddpcb *ddp, struct sockaddr *addr,
27 struct thread *td);
28static int at_pcbconnect(struct ddpcb *ddp, struct sockaddr *addr,
29 struct thread *td);
30static void at_pcbdetach(struct socket *so, struct ddpcb *ddp);
31static int at_pcballoc(struct socket *so);
32
33struct ddpcb *ddp_ports[ ATPORT_LAST ];
34struct ddpcb *ddpcb = NULL;
35static u_long ddp_sendspace = DDP_MAXSZ; /* Max ddp size + 1 (ddp_type) */
36static u_long ddp_recvspace = 10 * ( 587 + sizeof( struct sockaddr_at ));
37
38static struct ifqueue atintrq1, atintrq2, aarpintrq;
38
39static int
40ddp_attach(struct socket *so, int proto, struct thread *td)
41{
42 struct ddpcb *ddp;
43 int error = 0;
44 int s;
45
46
47 ddp = sotoddpcb( so );
48 if ( ddp != NULL ) {
49 return( EINVAL);
50 }
51
52 s = splnet();
53 error = at_pcballoc( so );
54 splx(s);
55 if (error) {
56 return (error);
57 }
58 return (soreserve( so, ddp_sendspace, ddp_recvspace ));
59}
60
61static int
62ddp_detach(struct socket *so)
63{
64 struct ddpcb *ddp;
65 int s;
66
67 ddp = sotoddpcb( so );
68 if ( ddp == NULL ) {
69 return( EINVAL);
70 }
71 s = splnet();
72 at_pcbdetach( so, ddp );
73 splx(s);
74 return(0);
75}
76
77static int
78ddp_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
79{
80 struct ddpcb *ddp;
81 int error = 0;
82 int s;
83
84 ddp = sotoddpcb( so );
85 if ( ddp == NULL ) {
86 return( EINVAL);
87 }
88 s = splnet();
89 error = at_pcbsetaddr(ddp, nam, td);
90 splx(s);
91 return (error);
92}
93
94static int
95ddp_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
96{
97 struct ddpcb *ddp;
98 int error = 0;
99 int s;
100
101 ddp = sotoddpcb( so );
102 if ( ddp == NULL ) {
103 return( EINVAL);
104 }
105
106 if ( ddp->ddp_fsat.sat_port != ATADDR_ANYPORT ) {
107 return(EISCONN);
108 }
109
110 s = splnet();
111 error = at_pcbconnect( ddp, nam, td );
112 splx(s);
113 if ( error == 0 )
114 soisconnected( so );
115 return(error);
116}
117
118static int
119ddp_disconnect(struct socket *so)
120{
121
122 struct ddpcb *ddp;
123 int s;
124
125 ddp = sotoddpcb( so );
126 if ( ddp == NULL ) {
127 return( EINVAL);
128 }
129 if ( ddp->ddp_fsat.sat_addr.s_node == ATADDR_ANYNODE ) {
130 return(ENOTCONN);
131 }
132
133 s = splnet();
134 at_pcbdisconnect( ddp );
135 ddp->ddp_fsat.sat_addr.s_node = ATADDR_ANYNODE;
136 splx(s);
137 soisdisconnected( so );
138 return(0);
139}
140
141static int
142ddp_shutdown(struct socket *so)
143{
144 struct ddpcb *ddp;
145
146 ddp = sotoddpcb( so );
147 if ( ddp == NULL ) {
148 return( EINVAL);
149 }
150 socantsendmore( so );
151 return(0);
152}
153
154static int
155ddp_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
156 struct mbuf *control, struct thread *td)
157{
158 struct ddpcb *ddp;
159 int error = 0;
160 int s;
161
162 ddp = sotoddpcb( so );
163 if ( ddp == NULL ) {
164 return(EINVAL);
165 }
166
167 if ( control && control->m_len ) {
168 return(EINVAL);
169 }
170
171 if ( addr ) {
172 if ( ddp->ddp_fsat.sat_port != ATADDR_ANYPORT ) {
173 return(EISCONN);
174 }
175
176 s = splnet();
177 error = at_pcbconnect(ddp, addr, td);
178 splx( s );
179 if ( error ) {
180 return(error);
181 }
182 } else {
183 if ( ddp->ddp_fsat.sat_port == ATADDR_ANYPORT ) {
184 return(ENOTCONN);
185 }
186 }
187
188 s = splnet();
189 error = ddp_output( m, so );
190 if ( addr ) {
191 at_pcbdisconnect( ddp );
192 }
193 splx(s);
194 return(error);
195}
196
197static int
198ddp_abort(struct socket *so)
199{
200 struct ddpcb *ddp;
201 int s;
202
203 ddp = sotoddpcb( so );
204 if ( ddp == NULL ) {
205 return(EINVAL);
206 }
207 soisdisconnected( so );
208 s = splnet();
209 at_pcbdetach( so, ddp );
210 splx(s);
211 return(0);
212}
213
214
215static void
216at_sockaddr(struct ddpcb *ddp, struct sockaddr **addr)
217{
218 *addr = dup_sockaddr((struct sockaddr *)&ddp->ddp_lsat, 0);
219}
220
221static int
222at_pcbsetaddr(struct ddpcb *ddp, struct sockaddr *addr, struct thread *td)
223{
224 struct sockaddr_at lsat, *sat;
225 struct at_ifaddr *aa;
226 struct ddpcb *ddpp;
227
228 if ( ddp->ddp_lsat.sat_port != ATADDR_ANYPORT ) { /* shouldn't be bound */
229 return( EINVAL );
230 }
231
232 if (addr != 0) { /* validate passed address */
233 sat = (struct sockaddr_at *)addr;
234 if (sat->sat_family != AF_APPLETALK) {
235 return(EAFNOSUPPORT);
236 }
237
238 if ( sat->sat_addr.s_node != ATADDR_ANYNODE ||
239 sat->sat_addr.s_net != ATADDR_ANYNET ) {
240 for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
241 if (( sat->sat_addr.s_net == AA_SAT( aa )->sat_addr.s_net ) &&
242 ( sat->sat_addr.s_node == AA_SAT( aa )->sat_addr.s_node )) {
243 break;
244 }
245 }
246 if ( !aa ) {
247 return( EADDRNOTAVAIL );
248 }
249 }
250
251 if ( sat->sat_port != ATADDR_ANYPORT ) {
252 if ( sat->sat_port < ATPORT_FIRST ||
253 sat->sat_port >= ATPORT_LAST ) {
254 return( EINVAL );
255 }
256 if ( sat->sat_port < ATPORT_RESERVED &&
257 suser(td) ) {
258 return( EACCES );
259 }
260 }
261 } else {
262 bzero( (caddr_t)&lsat, sizeof( struct sockaddr_at ));
263 lsat.sat_len = sizeof(struct sockaddr_at);
264 lsat.sat_addr.s_node = ATADDR_ANYNODE;
265 lsat.sat_addr.s_net = ATADDR_ANYNET;
266 lsat.sat_family = AF_APPLETALK;
267 sat = &lsat;
268 }
269
270 if ( sat->sat_addr.s_node == ATADDR_ANYNODE &&
271 sat->sat_addr.s_net == ATADDR_ANYNET ) {
272 if ( at_ifaddr == NULL ) {
273 return( EADDRNOTAVAIL );
274 }
275 sat->sat_addr = AA_SAT( at_ifaddr )->sat_addr;
276 }
277 ddp->ddp_lsat = *sat;
278
279 /*
280 * Choose port.
281 */
282 if ( sat->sat_port == ATADDR_ANYPORT ) {
283 for ( sat->sat_port = ATPORT_RESERVED;
284 sat->sat_port < ATPORT_LAST; sat->sat_port++ ) {
285 if ( ddp_ports[ sat->sat_port - 1 ] == 0 ) {
286 break;
287 }
288 }
289 if ( sat->sat_port == ATPORT_LAST ) {
290 return( EADDRNOTAVAIL );
291 }
292 ddp->ddp_lsat.sat_port = sat->sat_port;
293 ddp_ports[ sat->sat_port - 1 ] = ddp;
294 } else {
295 for ( ddpp = ddp_ports[ sat->sat_port - 1 ]; ddpp;
296 ddpp = ddpp->ddp_pnext ) {
297 if ( ddpp->ddp_lsat.sat_addr.s_net == sat->sat_addr.s_net &&
298 ddpp->ddp_lsat.sat_addr.s_node == sat->sat_addr.s_node ) {
299 break;
300 }
301 }
302 if ( ddpp != NULL ) {
303 return( EADDRINUSE );
304 }
305 ddp->ddp_pnext = ddp_ports[ sat->sat_port - 1 ];
306 ddp_ports[ sat->sat_port - 1 ] = ddp;
307 if ( ddp->ddp_pnext ) {
308 ddp->ddp_pnext->ddp_pprev = ddp;
309 }
310 }
311
312 return( 0 );
313}
314
315static int
316at_pcbconnect(struct ddpcb *ddp, struct sockaddr *addr, struct thread *td)
317{
318 struct sockaddr_at *sat = (struct sockaddr_at *)addr;
319 struct route *ro;
320 struct at_ifaddr *aa = 0;
321 struct ifnet *ifp;
322 u_short hintnet = 0, net;
323
324 if (sat->sat_family != AF_APPLETALK) {
325 return(EAFNOSUPPORT);
326 }
327
328 /*
329 * Under phase 2, network 0 means "the network". We take "the
330 * network" to mean the network the control block is bound to.
331 * If the control block is not bound, there is an error.
332 */
333 if ( sat->sat_addr.s_net == ATADDR_ANYNET
334 && sat->sat_addr.s_node != ATADDR_ANYNODE ) {
335 if ( ddp->ddp_lsat.sat_port == ATADDR_ANYPORT ) {
336 return( EADDRNOTAVAIL );
337 }
338 hintnet = ddp->ddp_lsat.sat_addr.s_net;
339 }
340
341 ro = &ddp->ddp_route;
342 /*
343 * If we've got an old route for this pcb, check that it is valid.
344 * If we've changed our address, we may have an old "good looking"
345 * route here. Attempt to detect it.
346 */
347 if ( ro->ro_rt ) {
348 if ( hintnet ) {
349 net = hintnet;
350 } else {
351 net = sat->sat_addr.s_net;
352 }
353 aa = 0;
354 if ((ifp = ro->ro_rt->rt_ifp) != NULL) {
355 for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
356 if ( aa->aa_ifp == ifp &&
357 ntohs( net ) >= ntohs( aa->aa_firstnet ) &&
358 ntohs( net ) <= ntohs( aa->aa_lastnet )) {
359 break;
360 }
361 }
362 }
363 if ( aa == NULL || ( satosat( &ro->ro_dst )->sat_addr.s_net !=
364 ( hintnet ? hintnet : sat->sat_addr.s_net ) ||
365 satosat( &ro->ro_dst )->sat_addr.s_node !=
366 sat->sat_addr.s_node )) {
367 RTFREE( ro->ro_rt );
368 ro->ro_rt = (struct rtentry *)0;
369 }
370 }
371
372 /*
373 * If we've got no route for this interface, try to find one.
374 */
375 if ( ro->ro_rt == (struct rtentry *)0 ||
376 ro->ro_rt->rt_ifp == (struct ifnet *)0 ) {
377 ro->ro_dst.sa_len = sizeof( struct sockaddr_at );
378 ro->ro_dst.sa_family = AF_APPLETALK;
379 if ( hintnet ) {
380 satosat( &ro->ro_dst )->sat_addr.s_net = hintnet;
381 } else {
382 satosat( &ro->ro_dst )->sat_addr.s_net = sat->sat_addr.s_net;
383 }
384 satosat( &ro->ro_dst )->sat_addr.s_node = sat->sat_addr.s_node;
385 rtalloc( ro );
386 }
387
388 /*
389 * Make sure any route that we have has a valid interface.
390 */
391 aa = 0;
392 if ( ro->ro_rt && ( ifp = ro->ro_rt->rt_ifp )) {
393 for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
394 if ( aa->aa_ifp == ifp ) {
395 break;
396 }
397 }
398 }
399 if ( aa == 0 ) {
400 return( ENETUNREACH );
401 }
402
403 ddp->ddp_fsat = *sat;
404 if ( ddp->ddp_lsat.sat_port == ATADDR_ANYPORT ) {
405 return(at_pcbsetaddr(ddp, (struct sockaddr *)0, td));
406 }
407 return( 0 );
408}
409
410static void
411at_pcbdisconnect( struct ddpcb *ddp )
412{
413 ddp->ddp_fsat.sat_addr.s_net = ATADDR_ANYNET;
414 ddp->ddp_fsat.sat_addr.s_node = ATADDR_ANYNODE;
415 ddp->ddp_fsat.sat_port = ATADDR_ANYPORT;
416}
417
418static int
419at_pcballoc( struct socket *so )
420{
421 struct ddpcb *ddp;
422
423 MALLOC(ddp, struct ddpcb *, sizeof *ddp, M_PCB, M_WAITOK | M_ZERO);
424 ddp->ddp_lsat.sat_port = ATADDR_ANYPORT;
425
426 ddp->ddp_next = ddpcb;
427 ddp->ddp_prev = NULL;
428 ddp->ddp_pprev = NULL;
429 ddp->ddp_pnext = NULL;
430 if (ddpcb) {
431 ddpcb->ddp_prev = ddp;
432 }
433 ddpcb = ddp;
434
435 ddp->ddp_socket = so;
436 so->so_pcb = (caddr_t)ddp;
437 return(0);
438}
439
440static void
441at_pcbdetach( struct socket *so, struct ddpcb *ddp)
442{
443 soisdisconnected( so );
444 so->so_pcb = 0;
445 sotryfree(so);
446
447 /* remove ddp from ddp_ports list */
448 if ( ddp->ddp_lsat.sat_port != ATADDR_ANYPORT &&
449 ddp_ports[ ddp->ddp_lsat.sat_port - 1 ] != NULL ) {
450 if ( ddp->ddp_pprev != NULL ) {
451 ddp->ddp_pprev->ddp_pnext = ddp->ddp_pnext;
452 } else {
453 ddp_ports[ ddp->ddp_lsat.sat_port - 1 ] = ddp->ddp_pnext;
454 }
455 if ( ddp->ddp_pnext != NULL ) {
456 ddp->ddp_pnext->ddp_pprev = ddp->ddp_pprev;
457 }
458 }
459
460 if ( ddp->ddp_route.ro_rt ) {
461 rtfree( ddp->ddp_route.ro_rt );
462 }
463
464 if ( ddp->ddp_prev ) {
465 ddp->ddp_prev->ddp_next = ddp->ddp_next;
466 } else {
467 ddpcb = ddp->ddp_next;
468 }
469 if ( ddp->ddp_next ) {
470 ddp->ddp_next->ddp_prev = ddp->ddp_prev;
471 }
472 FREE(ddp, M_PCB);
473}
474
475/*
476 * For the moment, this just find the pcb with the correct local address.
477 * In the future, this will actually do some real searching, so we can use
478 * the sender's address to do de-multiplexing on a single port to many
479 * sockets (pcbs).
480 */
481struct ddpcb *
482ddp_search( struct sockaddr_at *from, struct sockaddr_at *to,
483 struct at_ifaddr *aa)
484{
485 struct ddpcb *ddp;
486
487 /*
488 * Check for bad ports.
489 */
490 if ( to->sat_port < ATPORT_FIRST || to->sat_port >= ATPORT_LAST ) {
491 return( NULL );
492 }
493
494 /*
495 * Make sure the local address matches the sent address. What about
496 * the interface?
497 */
498 for ( ddp = ddp_ports[ to->sat_port - 1 ]; ddp; ddp = ddp->ddp_pnext ) {
499 /* XXX should we handle 0.YY? */
500
501 /* XXXX.YY to socket on destination interface */
502 if ( to->sat_addr.s_net == ddp->ddp_lsat.sat_addr.s_net &&
503 to->sat_addr.s_node == ddp->ddp_lsat.sat_addr.s_node ) {
504 break;
505 }
506
507 /* 0.255 to socket on receiving interface */
508 if ( to->sat_addr.s_node == ATADDR_BCAST && ( to->sat_addr.s_net == 0 ||
509 to->sat_addr.s_net == ddp->ddp_lsat.sat_addr.s_net ) &&
510 ddp->ddp_lsat.sat_addr.s_net == AA_SAT( aa )->sat_addr.s_net ) {
511 break;
512 }
513
514 /* XXXX.0 to socket on destination interface */
515 if ( to->sat_addr.s_net == aa->aa_firstnet &&
516 to->sat_addr.s_node == 0 &&
517 ntohs( ddp->ddp_lsat.sat_addr.s_net ) >=
518 ntohs( aa->aa_firstnet ) &&
519 ntohs( ddp->ddp_lsat.sat_addr.s_net ) <=
520 ntohs( aa->aa_lastnet )) {
521 break;
522 }
523 }
524 return( ddp );
525}
526static int
527at_setpeeraddr(struct socket *so, struct sockaddr **nam)
528{
529 return(EOPNOTSUPP);
530}
531
532static int
533at_setsockaddr(struct socket *so, struct sockaddr **nam)
534{
535 struct ddpcb *ddp;
536
537 ddp = sotoddpcb( so );
538 if ( ddp == NULL ) {
539 return( EINVAL);
540 }
541 at_sockaddr( ddp, nam );
542 return(0);
543}
544
39
40static int
41ddp_attach(struct socket *so, int proto, struct thread *td)
42{
43 struct ddpcb *ddp;
44 int error = 0;
45 int s;
46
47
48 ddp = sotoddpcb( so );
49 if ( ddp != NULL ) {
50 return( EINVAL);
51 }
52
53 s = splnet();
54 error = at_pcballoc( so );
55 splx(s);
56 if (error) {
57 return (error);
58 }
59 return (soreserve( so, ddp_sendspace, ddp_recvspace ));
60}
61
62static int
63ddp_detach(struct socket *so)
64{
65 struct ddpcb *ddp;
66 int s;
67
68 ddp = sotoddpcb( so );
69 if ( ddp == NULL ) {
70 return( EINVAL);
71 }
72 s = splnet();
73 at_pcbdetach( so, ddp );
74 splx(s);
75 return(0);
76}
77
78static int
79ddp_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
80{
81 struct ddpcb *ddp;
82 int error = 0;
83 int s;
84
85 ddp = sotoddpcb( so );
86 if ( ddp == NULL ) {
87 return( EINVAL);
88 }
89 s = splnet();
90 error = at_pcbsetaddr(ddp, nam, td);
91 splx(s);
92 return (error);
93}
94
95static int
96ddp_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
97{
98 struct ddpcb *ddp;
99 int error = 0;
100 int s;
101
102 ddp = sotoddpcb( so );
103 if ( ddp == NULL ) {
104 return( EINVAL);
105 }
106
107 if ( ddp->ddp_fsat.sat_port != ATADDR_ANYPORT ) {
108 return(EISCONN);
109 }
110
111 s = splnet();
112 error = at_pcbconnect( ddp, nam, td );
113 splx(s);
114 if ( error == 0 )
115 soisconnected( so );
116 return(error);
117}
118
119static int
120ddp_disconnect(struct socket *so)
121{
122
123 struct ddpcb *ddp;
124 int s;
125
126 ddp = sotoddpcb( so );
127 if ( ddp == NULL ) {
128 return( EINVAL);
129 }
130 if ( ddp->ddp_fsat.sat_addr.s_node == ATADDR_ANYNODE ) {
131 return(ENOTCONN);
132 }
133
134 s = splnet();
135 at_pcbdisconnect( ddp );
136 ddp->ddp_fsat.sat_addr.s_node = ATADDR_ANYNODE;
137 splx(s);
138 soisdisconnected( so );
139 return(0);
140}
141
142static int
143ddp_shutdown(struct socket *so)
144{
145 struct ddpcb *ddp;
146
147 ddp = sotoddpcb( so );
148 if ( ddp == NULL ) {
149 return( EINVAL);
150 }
151 socantsendmore( so );
152 return(0);
153}
154
155static int
156ddp_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
157 struct mbuf *control, struct thread *td)
158{
159 struct ddpcb *ddp;
160 int error = 0;
161 int s;
162
163 ddp = sotoddpcb( so );
164 if ( ddp == NULL ) {
165 return(EINVAL);
166 }
167
168 if ( control && control->m_len ) {
169 return(EINVAL);
170 }
171
172 if ( addr ) {
173 if ( ddp->ddp_fsat.sat_port != ATADDR_ANYPORT ) {
174 return(EISCONN);
175 }
176
177 s = splnet();
178 error = at_pcbconnect(ddp, addr, td);
179 splx( s );
180 if ( error ) {
181 return(error);
182 }
183 } else {
184 if ( ddp->ddp_fsat.sat_port == ATADDR_ANYPORT ) {
185 return(ENOTCONN);
186 }
187 }
188
189 s = splnet();
190 error = ddp_output( m, so );
191 if ( addr ) {
192 at_pcbdisconnect( ddp );
193 }
194 splx(s);
195 return(error);
196}
197
198static int
199ddp_abort(struct socket *so)
200{
201 struct ddpcb *ddp;
202 int s;
203
204 ddp = sotoddpcb( so );
205 if ( ddp == NULL ) {
206 return(EINVAL);
207 }
208 soisdisconnected( so );
209 s = splnet();
210 at_pcbdetach( so, ddp );
211 splx(s);
212 return(0);
213}
214
215
216static void
217at_sockaddr(struct ddpcb *ddp, struct sockaddr **addr)
218{
219 *addr = dup_sockaddr((struct sockaddr *)&ddp->ddp_lsat, 0);
220}
221
222static int
223at_pcbsetaddr(struct ddpcb *ddp, struct sockaddr *addr, struct thread *td)
224{
225 struct sockaddr_at lsat, *sat;
226 struct at_ifaddr *aa;
227 struct ddpcb *ddpp;
228
229 if ( ddp->ddp_lsat.sat_port != ATADDR_ANYPORT ) { /* shouldn't be bound */
230 return( EINVAL );
231 }
232
233 if (addr != 0) { /* validate passed address */
234 sat = (struct sockaddr_at *)addr;
235 if (sat->sat_family != AF_APPLETALK) {
236 return(EAFNOSUPPORT);
237 }
238
239 if ( sat->sat_addr.s_node != ATADDR_ANYNODE ||
240 sat->sat_addr.s_net != ATADDR_ANYNET ) {
241 for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
242 if (( sat->sat_addr.s_net == AA_SAT( aa )->sat_addr.s_net ) &&
243 ( sat->sat_addr.s_node == AA_SAT( aa )->sat_addr.s_node )) {
244 break;
245 }
246 }
247 if ( !aa ) {
248 return( EADDRNOTAVAIL );
249 }
250 }
251
252 if ( sat->sat_port != ATADDR_ANYPORT ) {
253 if ( sat->sat_port < ATPORT_FIRST ||
254 sat->sat_port >= ATPORT_LAST ) {
255 return( EINVAL );
256 }
257 if ( sat->sat_port < ATPORT_RESERVED &&
258 suser(td) ) {
259 return( EACCES );
260 }
261 }
262 } else {
263 bzero( (caddr_t)&lsat, sizeof( struct sockaddr_at ));
264 lsat.sat_len = sizeof(struct sockaddr_at);
265 lsat.sat_addr.s_node = ATADDR_ANYNODE;
266 lsat.sat_addr.s_net = ATADDR_ANYNET;
267 lsat.sat_family = AF_APPLETALK;
268 sat = &lsat;
269 }
270
271 if ( sat->sat_addr.s_node == ATADDR_ANYNODE &&
272 sat->sat_addr.s_net == ATADDR_ANYNET ) {
273 if ( at_ifaddr == NULL ) {
274 return( EADDRNOTAVAIL );
275 }
276 sat->sat_addr = AA_SAT( at_ifaddr )->sat_addr;
277 }
278 ddp->ddp_lsat = *sat;
279
280 /*
281 * Choose port.
282 */
283 if ( sat->sat_port == ATADDR_ANYPORT ) {
284 for ( sat->sat_port = ATPORT_RESERVED;
285 sat->sat_port < ATPORT_LAST; sat->sat_port++ ) {
286 if ( ddp_ports[ sat->sat_port - 1 ] == 0 ) {
287 break;
288 }
289 }
290 if ( sat->sat_port == ATPORT_LAST ) {
291 return( EADDRNOTAVAIL );
292 }
293 ddp->ddp_lsat.sat_port = sat->sat_port;
294 ddp_ports[ sat->sat_port - 1 ] = ddp;
295 } else {
296 for ( ddpp = ddp_ports[ sat->sat_port - 1 ]; ddpp;
297 ddpp = ddpp->ddp_pnext ) {
298 if ( ddpp->ddp_lsat.sat_addr.s_net == sat->sat_addr.s_net &&
299 ddpp->ddp_lsat.sat_addr.s_node == sat->sat_addr.s_node ) {
300 break;
301 }
302 }
303 if ( ddpp != NULL ) {
304 return( EADDRINUSE );
305 }
306 ddp->ddp_pnext = ddp_ports[ sat->sat_port - 1 ];
307 ddp_ports[ sat->sat_port - 1 ] = ddp;
308 if ( ddp->ddp_pnext ) {
309 ddp->ddp_pnext->ddp_pprev = ddp;
310 }
311 }
312
313 return( 0 );
314}
315
316static int
317at_pcbconnect(struct ddpcb *ddp, struct sockaddr *addr, struct thread *td)
318{
319 struct sockaddr_at *sat = (struct sockaddr_at *)addr;
320 struct route *ro;
321 struct at_ifaddr *aa = 0;
322 struct ifnet *ifp;
323 u_short hintnet = 0, net;
324
325 if (sat->sat_family != AF_APPLETALK) {
326 return(EAFNOSUPPORT);
327 }
328
329 /*
330 * Under phase 2, network 0 means "the network". We take "the
331 * network" to mean the network the control block is bound to.
332 * If the control block is not bound, there is an error.
333 */
334 if ( sat->sat_addr.s_net == ATADDR_ANYNET
335 && sat->sat_addr.s_node != ATADDR_ANYNODE ) {
336 if ( ddp->ddp_lsat.sat_port == ATADDR_ANYPORT ) {
337 return( EADDRNOTAVAIL );
338 }
339 hintnet = ddp->ddp_lsat.sat_addr.s_net;
340 }
341
342 ro = &ddp->ddp_route;
343 /*
344 * If we've got an old route for this pcb, check that it is valid.
345 * If we've changed our address, we may have an old "good looking"
346 * route here. Attempt to detect it.
347 */
348 if ( ro->ro_rt ) {
349 if ( hintnet ) {
350 net = hintnet;
351 } else {
352 net = sat->sat_addr.s_net;
353 }
354 aa = 0;
355 if ((ifp = ro->ro_rt->rt_ifp) != NULL) {
356 for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
357 if ( aa->aa_ifp == ifp &&
358 ntohs( net ) >= ntohs( aa->aa_firstnet ) &&
359 ntohs( net ) <= ntohs( aa->aa_lastnet )) {
360 break;
361 }
362 }
363 }
364 if ( aa == NULL || ( satosat( &ro->ro_dst )->sat_addr.s_net !=
365 ( hintnet ? hintnet : sat->sat_addr.s_net ) ||
366 satosat( &ro->ro_dst )->sat_addr.s_node !=
367 sat->sat_addr.s_node )) {
368 RTFREE( ro->ro_rt );
369 ro->ro_rt = (struct rtentry *)0;
370 }
371 }
372
373 /*
374 * If we've got no route for this interface, try to find one.
375 */
376 if ( ro->ro_rt == (struct rtentry *)0 ||
377 ro->ro_rt->rt_ifp == (struct ifnet *)0 ) {
378 ro->ro_dst.sa_len = sizeof( struct sockaddr_at );
379 ro->ro_dst.sa_family = AF_APPLETALK;
380 if ( hintnet ) {
381 satosat( &ro->ro_dst )->sat_addr.s_net = hintnet;
382 } else {
383 satosat( &ro->ro_dst )->sat_addr.s_net = sat->sat_addr.s_net;
384 }
385 satosat( &ro->ro_dst )->sat_addr.s_node = sat->sat_addr.s_node;
386 rtalloc( ro );
387 }
388
389 /*
390 * Make sure any route that we have has a valid interface.
391 */
392 aa = 0;
393 if ( ro->ro_rt && ( ifp = ro->ro_rt->rt_ifp )) {
394 for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
395 if ( aa->aa_ifp == ifp ) {
396 break;
397 }
398 }
399 }
400 if ( aa == 0 ) {
401 return( ENETUNREACH );
402 }
403
404 ddp->ddp_fsat = *sat;
405 if ( ddp->ddp_lsat.sat_port == ATADDR_ANYPORT ) {
406 return(at_pcbsetaddr(ddp, (struct sockaddr *)0, td));
407 }
408 return( 0 );
409}
410
411static void
412at_pcbdisconnect( struct ddpcb *ddp )
413{
414 ddp->ddp_fsat.sat_addr.s_net = ATADDR_ANYNET;
415 ddp->ddp_fsat.sat_addr.s_node = ATADDR_ANYNODE;
416 ddp->ddp_fsat.sat_port = ATADDR_ANYPORT;
417}
418
419static int
420at_pcballoc( struct socket *so )
421{
422 struct ddpcb *ddp;
423
424 MALLOC(ddp, struct ddpcb *, sizeof *ddp, M_PCB, M_WAITOK | M_ZERO);
425 ddp->ddp_lsat.sat_port = ATADDR_ANYPORT;
426
427 ddp->ddp_next = ddpcb;
428 ddp->ddp_prev = NULL;
429 ddp->ddp_pprev = NULL;
430 ddp->ddp_pnext = NULL;
431 if (ddpcb) {
432 ddpcb->ddp_prev = ddp;
433 }
434 ddpcb = ddp;
435
436 ddp->ddp_socket = so;
437 so->so_pcb = (caddr_t)ddp;
438 return(0);
439}
440
441static void
442at_pcbdetach( struct socket *so, struct ddpcb *ddp)
443{
444 soisdisconnected( so );
445 so->so_pcb = 0;
446 sotryfree(so);
447
448 /* remove ddp from ddp_ports list */
449 if ( ddp->ddp_lsat.sat_port != ATADDR_ANYPORT &&
450 ddp_ports[ ddp->ddp_lsat.sat_port - 1 ] != NULL ) {
451 if ( ddp->ddp_pprev != NULL ) {
452 ddp->ddp_pprev->ddp_pnext = ddp->ddp_pnext;
453 } else {
454 ddp_ports[ ddp->ddp_lsat.sat_port - 1 ] = ddp->ddp_pnext;
455 }
456 if ( ddp->ddp_pnext != NULL ) {
457 ddp->ddp_pnext->ddp_pprev = ddp->ddp_pprev;
458 }
459 }
460
461 if ( ddp->ddp_route.ro_rt ) {
462 rtfree( ddp->ddp_route.ro_rt );
463 }
464
465 if ( ddp->ddp_prev ) {
466 ddp->ddp_prev->ddp_next = ddp->ddp_next;
467 } else {
468 ddpcb = ddp->ddp_next;
469 }
470 if ( ddp->ddp_next ) {
471 ddp->ddp_next->ddp_prev = ddp->ddp_prev;
472 }
473 FREE(ddp, M_PCB);
474}
475
476/*
477 * For the moment, this just find the pcb with the correct local address.
478 * In the future, this will actually do some real searching, so we can use
479 * the sender's address to do de-multiplexing on a single port to many
480 * sockets (pcbs).
481 */
482struct ddpcb *
483ddp_search( struct sockaddr_at *from, struct sockaddr_at *to,
484 struct at_ifaddr *aa)
485{
486 struct ddpcb *ddp;
487
488 /*
489 * Check for bad ports.
490 */
491 if ( to->sat_port < ATPORT_FIRST || to->sat_port >= ATPORT_LAST ) {
492 return( NULL );
493 }
494
495 /*
496 * Make sure the local address matches the sent address. What about
497 * the interface?
498 */
499 for ( ddp = ddp_ports[ to->sat_port - 1 ]; ddp; ddp = ddp->ddp_pnext ) {
500 /* XXX should we handle 0.YY? */
501
502 /* XXXX.YY to socket on destination interface */
503 if ( to->sat_addr.s_net == ddp->ddp_lsat.sat_addr.s_net &&
504 to->sat_addr.s_node == ddp->ddp_lsat.sat_addr.s_node ) {
505 break;
506 }
507
508 /* 0.255 to socket on receiving interface */
509 if ( to->sat_addr.s_node == ATADDR_BCAST && ( to->sat_addr.s_net == 0 ||
510 to->sat_addr.s_net == ddp->ddp_lsat.sat_addr.s_net ) &&
511 ddp->ddp_lsat.sat_addr.s_net == AA_SAT( aa )->sat_addr.s_net ) {
512 break;
513 }
514
515 /* XXXX.0 to socket on destination interface */
516 if ( to->sat_addr.s_net == aa->aa_firstnet &&
517 to->sat_addr.s_node == 0 &&
518 ntohs( ddp->ddp_lsat.sat_addr.s_net ) >=
519 ntohs( aa->aa_firstnet ) &&
520 ntohs( ddp->ddp_lsat.sat_addr.s_net ) <=
521 ntohs( aa->aa_lastnet )) {
522 break;
523 }
524 }
525 return( ddp );
526}
527static int
528at_setpeeraddr(struct socket *so, struct sockaddr **nam)
529{
530 return(EOPNOTSUPP);
531}
532
533static int
534at_setsockaddr(struct socket *so, struct sockaddr **nam)
535{
536 struct ddpcb *ddp;
537
538 ddp = sotoddpcb( so );
539 if ( ddp == NULL ) {
540 return( EINVAL);
541 }
542 at_sockaddr( ddp, nam );
543 return(0);
544}
545
545
546void
546void
547ddp_init(void )
547ddp_init(void)
548{
548{
549 atintrq1.ifq_maxlen = IFQ_MAXLEN;
550 atintrq2.ifq_maxlen = IFQ_MAXLEN;
551 atintrq1_present = 1;
552 atintrq2_present = 1;
553 mtx_init(&atintrq1.ifq_mtx, "at1_inq", NULL, MTX_DEF);
554 mtx_init(&atintrq2.ifq_mtx, "at2_inq", NULL, MTX_DEF);
549
550 atintrq1.ifq_maxlen = IFQ_MAXLEN;
551 atintrq2.ifq_maxlen = IFQ_MAXLEN;
552 aarpintrq.ifq_maxlen = IFQ_MAXLEN;
553 mtx_init(&atintrq1.ifq_mtx, "at1_inq", NULL, MTX_DEF);
554 mtx_init(&atintrq2.ifq_mtx, "at2_inq", NULL, MTX_DEF);
555 mtx_init(&aarpintrq.ifq_mtx, "aarp_inq", NULL, MTX_DEF);
556 netisr_register(NETISR_ATALK1, at1intr, &atintrq1);
557 netisr_register(NETISR_ATALK2, at2intr, &atintrq2);
558 netisr_register(NETISR_AARP, aarpintr, &aarpintrq);
555}
556
557#if 0
558static void
559ddp_clean(void )
560{
561 struct ddpcb *ddp;
562
563 for ( ddp = ddpcb; ddp; ddp = ddp->ddp_next ) {
564 at_pcbdetach( ddp->ddp_socket, ddp );
565 }
566}
567#endif
568
569struct pr_usrreqs ddp_usrreqs = {
570 ddp_abort,
571 pru_accept_notsupp,
572 ddp_attach,
573 ddp_bind,
574 ddp_connect,
575 pru_connect2_notsupp,
576 at_control,
577 ddp_detach,
578 ddp_disconnect,
579 pru_listen_notsupp,
580 at_setpeeraddr,
581 pru_rcvd_notsupp,
582 pru_rcvoob_notsupp,
583 ddp_send,
584 pru_sense_null,
585 ddp_shutdown,
586 at_setsockaddr,
587 sosend,
588 soreceive,
589 sopoll
590};
559}
560
561#if 0
562static void
563ddp_clean(void )
564{
565 struct ddpcb *ddp;
566
567 for ( ddp = ddpcb; ddp; ddp = ddp->ddp_next ) {
568 at_pcbdetach( ddp->ddp_socket, ddp );
569 }
570}
571#endif
572
573struct pr_usrreqs ddp_usrreqs = {
574 ddp_abort,
575 pru_accept_notsupp,
576 ddp_attach,
577 ddp_bind,
578 ddp_connect,
579 pru_connect2_notsupp,
580 at_control,
581 ddp_detach,
582 ddp_disconnect,
583 pru_listen_notsupp,
584 at_setpeeraddr,
585 pru_rcvd_notsupp,
586 pru_rcvoob_notsupp,
587 ddp_send,
588 pru_sense_null,
589 ddp_shutdown,
590 at_setsockaddr,
591 sosend,
592 soreceive,
593 sopoll
594};