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