This source file includes following definitions.
- ddp_usrreq
- at_sockaddr
- at_pcbsetaddr
- at_pcbconnect
- at_pcbdisconnect
- at_pcballoc
- at_pcbdetach
- ddp_search
- ddp_init
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 #include <sys/errno.h>
55 #include <sys/types.h>
56 #include <sys/param.h>
57 #include <sys/systm.h>
58 #include <sys/proc.h>
59 #include <sys/user.h>
60 #include <sys/mbuf.h>
61 #include <sys/ioctl.h>
62 #include <sys/socket.h>
63 #include <sys/socketvar.h>
64 #include <sys/protosw.h>
65 #include <net/if.h>
66 #include <net/route.h>
67
68 #include <machine/endian.h>
69
70 #include <netatalk/at.h>
71 #include <netatalk/at_var.h>
72 #include <netatalk/ddp_var.h>
73 #include <netatalk/at_extern.h>
74
75 int ddp_usrreq(struct socket *, int, struct mbuf *,
76 struct mbuf *, struct mbuf * );
77 static void at_sockaddr( struct ddpcb *, struct mbuf * );
78 static int at_pcbsetaddr( struct ddpcb *, struct mbuf *,
79 struct proc * );
80 static int at_pcbconnect( struct ddpcb *, struct mbuf *,
81 struct proc *);
82 static void at_pcbdisconnect( struct ddpcb * );
83 static int at_pcballoc( struct socket * );
84 static void at_pcbdetach( struct socket *, struct ddpcb * );
85 struct ddpcb *ddp_search( struct sockaddr_at *,
86 struct sockaddr_at *, struct at_ifaddr * );
87 void ddp_init(void);
88
89 struct at_ifaddr *at_ifaddr;
90 struct ifqueue atintrq1, atintrq2;
91 int atdebug;
92
93 struct ddpcb *ddp_ports[ ATPORT_LAST ];
94 struct ddpstat ddpstat;
95
96 struct ddpcb *ddpcb = NULL;
97 u_long ddp_sendspace = DDP_MAXSZ;
98 u_long ddp_recvspace = 10 * ( 587 + sizeof( struct sockaddr_at ));
99
100
101 int
102 ddp_usrreq( so, req, m, addr, rights )
103 struct socket *so;
104 int req;
105 struct mbuf *m, *addr, *rights;
106 {
107
108 struct proc *p = curproc;
109 struct ddpcb *ddp;
110 int error = 0;
111
112 ddp = sotoddpcb( so );
113
114 if ( req == PRU_CONTROL ) {
115 return( at_control( (u_long) m, (caddr_t) addr,
116 (struct ifnet *) rights, p ));
117 }
118
119 if ( rights && rights->m_len ) {
120 error = EINVAL;
121 goto release;
122 }
123
124 if ( ddp == NULL && req != PRU_ATTACH ) {
125 error = EINVAL;
126 goto release;
127 }
128
129 switch ( req ) {
130 case PRU_ATTACH :
131 if ( ddp != NULL ) {
132 error = EINVAL;
133 break;
134 }
135 if (( error = at_pcballoc( so )) != 0 ) {
136 break;
137 }
138 error = soreserve( so, ddp_sendspace, ddp_recvspace );
139 break;
140
141 case PRU_DETACH :
142 at_pcbdetach( so, ddp );
143 break;
144
145 case PRU_BIND :
146 error = at_pcbsetaddr( ddp, addr, p );
147 break;
148
149 case PRU_SOCKADDR :
150 at_sockaddr( ddp, addr );
151 break;
152
153 case PRU_CONNECT:
154 if ( ddp->ddp_fsat.sat_port != ATADDR_ANYPORT ) {
155 error = EISCONN;
156 break;
157 }
158
159 error = at_pcbconnect( ddp, addr, p );
160 if ( error == 0 )
161 soisconnected( so );
162 break;
163
164 case PRU_DISCONNECT:
165 if ( ddp->ddp_fsat.sat_addr.s_node == ATADDR_ANYNODE ) {
166 error = ENOTCONN;
167 break;
168 }
169 at_pcbdisconnect( ddp );
170 soisdisconnected( so );
171 break;
172
173 case PRU_SHUTDOWN:
174 socantsendmore( so );
175 break;
176
177 case PRU_SEND: {
178 int s;
179
180 if ( addr ) {
181 if ( ddp->ddp_fsat.sat_port != ATADDR_ANYPORT ) {
182 error = EISCONN;
183 break;
184 }
185
186 s = splnet();
187 error = at_pcbconnect( ddp, addr, p );
188 if ( error ) {
189 splx( s );
190 break;
191 }
192 } else {
193 if ( ddp->ddp_fsat.sat_port == ATADDR_ANYPORT ) {
194 error = ENOTCONN;
195 break;
196 }
197 }
198
199 error = ddp_output( m, ddp );
200 m = NULL;
201 if ( addr ) {
202 at_pcbdisconnect( ddp );
203 splx( s );
204 }
205 }
206 break;
207
208 case PRU_ABORT:
209 soisdisconnected( so );
210 at_pcbdetach( so, ddp );
211 break;
212
213 case PRU_LISTEN:
214 case PRU_CONNECT2:
215 case PRU_ACCEPT:
216 case PRU_SENDOOB:
217 case PRU_FASTTIMO:
218 case PRU_SLOWTIMO:
219 case PRU_PROTORCV:
220 case PRU_PROTOSEND:
221 error = EOPNOTSUPP;
222 break;
223
224 case PRU_RCVD:
225 case PRU_RCVOOB:
226
227
228
229 return( EOPNOTSUPP );
230
231 case PRU_SENSE:
232
233
234
235
236 return( 0 );
237
238 default:
239 error = EOPNOTSUPP;
240 }
241
242 release:
243 if ( m != NULL ) {
244 m_freem( m );
245 }
246 return( error );
247 }
248
249 static void
250 at_sockaddr( ddp, addr )
251 struct ddpcb *ddp;
252 struct mbuf *addr;
253 {
254 struct sockaddr_at *sat;
255
256 addr->m_len = sizeof( struct sockaddr_at );
257 sat = mtod( addr, struct sockaddr_at *);
258 *sat = ddp->ddp_lsat;
259 }
260
261 static int
262 at_pcbsetaddr( ddp, addr, p )
263 struct ddpcb *ddp;
264 struct mbuf *addr;
265 struct proc *p;
266 {
267 struct sockaddr_at lsat, *sat;
268 struct at_ifaddr *aa;
269 struct ddpcb *ddpp;
270
271 if ( ddp->ddp_lsat.sat_port != ATADDR_ANYPORT ) {
272 return( EINVAL );
273 }
274
275 if ( addr != 0 ) {
276 sat = mtod( addr, struct sockaddr_at *);
277 if ( addr->m_len != sizeof( *sat )) {
278 return( EINVAL );
279 }
280 if ( sat->sat_family != AF_APPLETALK ) {
281 return( EAFNOSUPPORT );
282 }
283
284 if ( sat->sat_addr.s_node != ATADDR_ANYNODE ||
285 sat->sat_addr.s_net != ATADDR_ANYNET ) {
286 for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
287 if (( sat->sat_addr.s_net == AA_SAT( aa )->sat_addr.s_net ) &&
288 ( sat->sat_addr.s_node == AA_SAT( aa )->sat_addr.s_node )) {
289 break;
290 }
291 }
292 if ( !aa ) {
293 return( EADDRNOTAVAIL );
294 }
295 }
296
297 if ( sat->sat_port != ATADDR_ANYPORT ) {
298 if ( sat->sat_port < ATPORT_FIRST ||
299 sat->sat_port >= ATPORT_LAST ) {
300 return( EINVAL );
301 }
302 if ( sat->sat_port < ATPORT_RESERVED &&
303 suser( p, 0 )) {
304 return( EACCES );
305 }
306 }
307 } else {
308 bzero( (caddr_t)&lsat, sizeof( struct sockaddr_at ));
309 lsat.sat_family = AF_APPLETALK;
310 sat = &lsat;
311 }
312
313 if ( sat->sat_addr.s_node == ATADDR_ANYNODE &&
314 sat->sat_addr.s_net == ATADDR_ANYNET ) {
315 if ( at_ifaddr == NULL ) {
316 return( EADDRNOTAVAIL );
317 }
318 sat->sat_addr = AA_SAT( at_ifaddr )->sat_addr;
319 }
320 ddp->ddp_lsat = *sat;
321
322
323
324
325 if ( sat->sat_port == ATADDR_ANYPORT ) {
326 for ( sat->sat_port = ATPORT_RESERVED;
327 sat->sat_port < ATPORT_LAST; sat->sat_port++ ) {
328 if ( ddp_ports[ sat->sat_port - 1 ] == 0 ) {
329 break;
330 }
331 }
332 if ( sat->sat_port == ATPORT_LAST ) {
333 return( EADDRNOTAVAIL );
334 }
335 ddp->ddp_lsat.sat_port = sat->sat_port;
336 ddp_ports[ sat->sat_port - 1 ] = ddp;
337 } else {
338 for ( ddpp = ddp_ports[ sat->sat_port - 1 ]; ddpp;
339 ddpp = ddpp->ddp_pnext ) {
340 if ( ddpp->ddp_lsat.sat_addr.s_net == sat->sat_addr.s_net &&
341 ddpp->ddp_lsat.sat_addr.s_node == sat->sat_addr.s_node ) {
342 break;
343 }
344 }
345 if ( ddpp != NULL ) {
346 return( EADDRINUSE );
347 }
348 ddp->ddp_pnext = ddp_ports[ sat->sat_port - 1 ];
349 ddp_ports[ sat->sat_port - 1 ] = ddp;
350 if ( ddp->ddp_pnext ) {
351 ddp->ddp_pnext->ddp_pprev = ddp;
352 }
353 }
354
355 return( 0 );
356 }
357
358 static int
359 at_pcbconnect( ddp, addr, p )
360 struct ddpcb *ddp;
361 struct mbuf *addr;
362 struct proc *p;
363 {
364 struct sockaddr_at *sat = mtod( addr, struct sockaddr_at *);
365 struct route *ro;
366 struct at_ifaddr *aa = 0;
367 struct ifnet *ifp;
368 u_int16_t hintnet = 0, net;
369
370 if ( addr->m_len != sizeof( *sat ))
371 return( EINVAL );
372 if ( sat->sat_family != AF_APPLETALK ) {
373 return( EAFNOSUPPORT );
374 }
375
376
377
378
379
380
381 if ( sat->sat_addr.s_net == 0 && sat->sat_addr.s_node != ATADDR_ANYNODE ) {
382 if ( ddp->ddp_lsat.sat_port == ATADDR_ANYPORT ) {
383 return( EADDRNOTAVAIL );
384 }
385 hintnet = ddp->ddp_lsat.sat_addr.s_net;
386 }
387
388 ro = &ddp->ddp_route;
389
390
391
392
393
394 if ( ro->ro_rt ) {
395 if ( hintnet ) {
396 net = hintnet;
397 } else {
398 net = sat->sat_addr.s_net;
399 }
400 aa = 0;
401 if ( (ifp = ro->ro_rt->rt_ifp) != NULL ) {
402 for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
403 if ( aa->aa_ifp == ifp &&
404 ntohs( net ) >= ntohs( aa->aa_firstnet ) &&
405 ntohs( net ) <= ntohs( aa->aa_lastnet )) {
406 break;
407 }
408 }
409 }
410 if ( aa == NULL || ( satosat( &ro->ro_dst )->sat_addr.s_net !=
411 ( hintnet ? hintnet : sat->sat_addr.s_net ) ||
412 satosat( &ro->ro_dst )->sat_addr.s_node !=
413 sat->sat_addr.s_node )) {
414 RTFREE( ro->ro_rt );
415 ro->ro_rt = (struct rtentry *)0;
416 }
417 }
418
419
420
421
422 if ( ro->ro_rt == (struct rtentry *)0 ||
423 ro->ro_rt->rt_ifp == (struct ifnet *)0 ) {
424 ro->ro_dst.sa_len = sizeof( struct sockaddr_at );
425 ro->ro_dst.sa_family = AF_APPLETALK;
426 if ( hintnet != 0 ) {
427 satosat( &ro->ro_dst )->sat_addr.s_net = hintnet;
428 } else {
429 satosat( &ro->ro_dst )->sat_addr.s_net = sat->sat_addr.s_net;
430 }
431 satosat( &ro->ro_dst )->sat_addr.s_node = sat->sat_addr.s_node;
432 rtalloc( ro );
433 }
434
435
436
437
438 aa = 0;
439 if ( ro->ro_rt && ( ifp = ro->ro_rt->rt_ifp )) {
440 for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
441 if ( aa->aa_ifp == ifp ) {
442 break;
443 }
444 }
445 }
446 if ( aa == 0 ) {
447 return( ENETUNREACH );
448 }
449
450 ddp->ddp_fsat = *sat;
451 if ( ddp->ddp_lsat.sat_port == ATADDR_ANYPORT ) {
452 return( at_pcbsetaddr( ddp, (struct mbuf *)0, p ));
453 }
454 return( 0 );
455 }
456
457 static void
458 at_pcbdisconnect( ddp )
459 struct ddpcb *ddp;
460 {
461 ddp->ddp_fsat.sat_addr.s_net = ATADDR_ANYNET;
462 ddp->ddp_fsat.sat_addr.s_node = ATADDR_ANYNODE;
463 ddp->ddp_fsat.sat_port = ATADDR_ANYPORT;
464 }
465
466 static int
467 at_pcballoc( so )
468 struct socket *so;
469 {
470 struct ddpcb *ddp;
471
472 MALLOC( ddp, struct ddpcb *, sizeof( *ddp ), M_PCB, M_NOWAIT );
473 if ( ddp == NULL ) {
474 return (ENOBUFS);
475 }
476 bzero( ddp, sizeof( *ddp ));
477
478 ddp->ddp_lsat.sat_port = ATADDR_ANYPORT;
479
480 ddp->ddp_next = ddpcb;
481 ddp->ddp_prev = NULL;
482 ddp->ddp_pprev = NULL;
483 ddp->ddp_pnext = NULL;
484 if ( ddpcb ) {
485 ddpcb->ddp_prev = ddp;
486 }
487 ddpcb = ddp;
488
489 ddp->ddp_socket = so;
490 so->so_pcb = (caddr_t)ddp;
491 return( 0 );
492 }
493
494 static void
495 at_pcbdetach( so, ddp )
496 struct socket *so;
497 struct ddpcb *ddp;
498 {
499 soisdisconnected( so );
500 so->so_pcb = 0;
501 sofree( so );
502
503
504 if ( ddp->ddp_lsat.sat_port != ATADDR_ANYPORT &&
505 ddp_ports[ ddp->ddp_lsat.sat_port - 1 ] != NULL ) {
506 if ( ddp->ddp_pprev != NULL ) {
507 ddp->ddp_pprev->ddp_pnext = ddp->ddp_pnext;
508 } else {
509 ddp_ports[ ddp->ddp_lsat.sat_port - 1 ] = ddp->ddp_pnext;
510 }
511 if ( ddp->ddp_pnext != NULL ) {
512 ddp->ddp_pnext->ddp_pprev = ddp->ddp_pprev;
513 }
514 }
515
516 if ( ddp->ddp_route.ro_rt ) {
517 rtfree( ddp->ddp_route.ro_rt );
518 }
519
520 if ( ddp->ddp_prev ) {
521 ddp->ddp_prev->ddp_next = ddp->ddp_next;
522 } else {
523 ddpcb = ddp->ddp_next;
524 }
525 if ( ddp->ddp_next ) {
526 ddp->ddp_next->ddp_prev = ddp->ddp_prev;
527 }
528
529 FREE( ddp, M_PCB );
530 }
531
532
533
534
535
536
537
538 struct ddpcb *
539 ddp_search( from, to, aa )
540 struct sockaddr_at *from, *to;
541 struct at_ifaddr *aa;
542 {
543 struct ddpcb *ddp;
544
545
546
547
548 if ( to->sat_port < ATPORT_FIRST || to->sat_port >= ATPORT_LAST ) {
549 return( NULL );
550 }
551
552
553
554
555
556 for ( ddp = ddp_ports[ to->sat_port - 1 ]; ddp; ddp = ddp->ddp_pnext ) {
557
558
559
560 if ( to->sat_addr.s_net == ddp->ddp_lsat.sat_addr.s_net &&
561 to->sat_addr.s_node == ddp->ddp_lsat.sat_addr.s_node ) {
562 break;
563 }
564
565
566 if ( to->sat_addr.s_node == ATADDR_BCAST && ( to->sat_addr.s_net == 0 ||
567 to->sat_addr.s_net == ddp->ddp_lsat.sat_addr.s_net ) &&
568 ddp->ddp_lsat.sat_addr.s_net == AA_SAT( aa )->sat_addr.s_net ) {
569 break;
570 }
571
572
573 if ( to->sat_addr.s_net == aa->aa_firstnet &&
574 to->sat_addr.s_node == 0 &&
575 ntohs( ddp->ddp_lsat.sat_addr.s_net ) >=
576 ntohs( aa->aa_firstnet ) &&
577 ntohs( ddp->ddp_lsat.sat_addr.s_net ) <=
578 ntohs( aa->aa_lastnet )) {
579 break;
580 }
581 }
582 return( ddp );
583 }
584
585 void
586 ddp_init()
587 {
588 atintrq1.ifq_maxlen = IFQ_MAXLEN;
589 atintrq2.ifq_maxlen = IFQ_MAXLEN;
590 }