2
* $Id: ddp_usrreq.c,v 1.2 2001/06/29 14:14:47 rufustfirefly Exp $
4
* Copyright (c) 1990,1994 Regents of The University of Michigan.
5
* All Rights Reserved. See COPYRIGHT.
10
#endif /* HAVE_CONFIG_H */
12
#include <sys/errno.h>
13
#include <sys/types.h>
14
#include <sys/param.h>
15
#include <sys/systm.h>
21
#include <sys/ioctl.h>
22
#include <sys/socket.h>
23
#include <sys/socketvar.h>
24
#include <sys/protosw.h>
26
#include <net/route.h>
36
struct ddpcb *ddpcb = NULL;
37
u_int32_t ddp_sendspace = DDP_MAXSZ; /* Max ddp size + 1 (ddp_type) */
38
u_int32_t ddp_recvspace = 10 * ( 587 + sizeof( struct sockaddr_at ));
41
ddp_usrreq( so, req, m, addr, rights )
44
struct mbuf *m, *addr, *rights;
49
ddp = sotoddpcb( so );
51
if ( req == PRU_CONTROL ) {
52
return( at_control( (int) m, (caddr_t) addr,
53
(struct ifnet *) rights ));
56
if ( rights && rights->m_len ) {
61
if ( ddp == NULL && req != PRU_ATTACH ) {
72
if (( error = at_pcballoc( so )) != 0 ) {
75
error = soreserve( so, ddp_sendspace, ddp_recvspace );
79
at_pcbdetach( so, ddp );
83
error = at_pcbsetaddr( ddp, addr );
87
at_sockaddr( ddp, addr );
91
if ( ddp->ddp_fsat.sat_port != ATADDR_ANYPORT ) {
96
error = at_pcbconnect( ddp, addr );
102
if ( ddp->ddp_fsat.sat_addr.s_node == ATADDR_ANYNODE ) {
106
at_pcbdisconnect( ddp );
107
soisdisconnected( so );
111
socantsendmore( so );
118
if ( ddp->ddp_fsat.sat_port != ATADDR_ANYPORT ) {
124
error = at_pcbconnect( ddp, addr );
130
if ( ddp->ddp_fsat.sat_port == ATADDR_ANYPORT ) {
136
error = ddp_output( ddp, m );
139
at_pcbdisconnect( ddp );
146
soisdisconnected( so );
147
at_pcbdetach( so, ddp );
164
* Don't mfree. Good architecture...
166
return( EOPNOTSUPP );
170
* 1. Don't return block size.
186
at_sockaddr( ddp, addr )
190
struct sockaddr_at *sat;
192
addr->m_len = sizeof( struct sockaddr_at );
193
sat = mtod( addr, struct sockaddr_at *);
194
*sat = ddp->ddp_lsat;
197
at_pcbsetaddr( ddp, addr )
201
struct sockaddr_at lsat, *sat;
202
struct at_ifaddr *aa;
205
if ( ddp->ddp_lsat.sat_port != ATADDR_ANYPORT ) { /* shouldn't be bound */
209
if ( addr != 0 ) { /* validate passed address */
210
sat = mtod( addr, struct sockaddr_at *);
211
if ( addr->m_len != sizeof( *sat )) {
214
if ( sat->sat_family != AF_APPLETALK ) {
215
return( EAFNOSUPPORT );
218
if ( sat->sat_addr.s_node != ATADDR_ANYNODE ||
219
sat->sat_addr.s_net != ATADDR_ANYNET ) {
220
for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
221
if (( sat->sat_addr.s_net == AA_SAT( aa )->sat_addr.s_net ) &&
222
( sat->sat_addr.s_node == AA_SAT( aa )->sat_addr.s_node )) {
227
return( EADDRNOTAVAIL );
231
if ( sat->sat_port != ATADDR_ANYPORT ) {
232
if ( sat->sat_port < ATPORT_FIRST ||
233
sat->sat_port >= ATPORT_LAST ) {
237
if ( sat->sat_port < ATPORT_RESERVED &&
238
suser( u.u_cred, &u.u_acflag )) {
242
if ( sat->sat_port < ATPORT_RESERVED && ( !suser())) {
248
bzero( (caddr_t)&lsat, sizeof( struct sockaddr_at ));
249
lsat.sat_family = AF_APPLETALK;
253
if ( sat->sat_addr.s_node == ATADDR_ANYNODE &&
254
sat->sat_addr.s_net == ATADDR_ANYNET ) {
255
if ( at_ifaddr == NULL ) {
256
return( EADDRNOTAVAIL );
258
sat->sat_addr = AA_SAT( at_ifaddr )->sat_addr;
260
ddp->ddp_lsat = *sat;
265
if ( sat->sat_port == ATADDR_ANYPORT ) {
266
for ( sat->sat_port = ATPORT_RESERVED;
267
sat->sat_port < ATPORT_LAST; sat->sat_port++ ) {
268
if ( ddp_ports[ sat->sat_port - 1 ] == 0 ) {
272
if ( sat->sat_port == ATPORT_LAST ) {
273
return( EADDRNOTAVAIL );
275
ddp->ddp_lsat.sat_port = sat->sat_port;
276
ddp_ports[ sat->sat_port - 1 ] = ddp;
278
for ( ddpp = ddp_ports[ sat->sat_port - 1 ]; ddpp;
279
ddpp = ddpp->ddp_pnext ) {
280
if ( ddpp->ddp_lsat.sat_addr.s_net == sat->sat_addr.s_net &&
281
ddpp->ddp_lsat.sat_addr.s_node == sat->sat_addr.s_node ) {
285
if ( ddpp != NULL ) {
286
return( EADDRINUSE );
288
ddp->ddp_pnext = ddp_ports[ sat->sat_port - 1 ];
289
ddp_ports[ sat->sat_port - 1 ] = ddp;
290
if ( ddp->ddp_pnext ) {
291
ddp->ddp_pnext->ddp_pprev = ddp;
298
at_pcbconnect( ddp, addr )
302
struct sockaddr_at *sat = mtod( addr, struct sockaddr_at *);
304
struct at_ifaddr *aa = 0;
306
u_short hintnet = 0, net;
308
if ( addr->m_len != sizeof( *sat ))
310
if ( sat->sat_family != AF_APPLETALK ) {
311
return( EAFNOSUPPORT );
315
* Under phase 2, network 0 means "the network". We take "the
316
* network" to mean the network the control block is bound to.
317
* If the control block is not bound, there is an error.
319
if ( sat->sat_addr.s_net == 0 && sat->sat_addr.s_node != ATADDR_ANYNODE ) {
320
if ( ddp->ddp_lsat.sat_port == ATADDR_ANYPORT ) {
321
return( EADDRNOTAVAIL );
323
hintnet = ddp->ddp_lsat.sat_addr.s_net;
326
ro = &ddp->ddp_route;
328
* If we've got an old route for this pcb, check that it is valid.
329
* If we've changed our address, we may have an old "good looking"
330
* route here. Attempt to detect it.
336
net = sat->sat_addr.s_net;
339
if ( ifp = ro->ro_rt->rt_ifp ) {
340
for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
341
if ( aa->aa_ifp == ifp &&
342
ntohs( net ) >= ntohs( aa->aa_firstnet ) &&
343
ntohs( net ) <= ntohs( aa->aa_lastnet )) {
348
if ( aa == NULL || ( satosat( &ro->ro_dst )->sat_addr.s_net !=
349
( hintnet ? hintnet : sat->sat_addr.s_net ) ||
350
satosat( &ro->ro_dst )->sat_addr.s_node !=
351
sat->sat_addr.s_node )) {
357
ro->ro_rt = (struct rtentry *)0;
362
* If we've got no route for this interface, try to find one.
364
if ( ro->ro_rt == (struct rtentry *)0 ||
365
ro->ro_rt->rt_ifp == (struct ifnet *)0 ) {
367
ro->ro_dst.sa_len = sizeof( struct sockaddr_at );
369
ro->ro_dst.sa_family = AF_APPLETALK;
370
if ( hintnet != 0 ) {
371
satosat( &ro->ro_dst )->sat_addr.s_net = hintnet;
373
satosat( &ro->ro_dst )->sat_addr.s_net = sat->sat_addr.s_net;
375
satosat( &ro->ro_dst )->sat_addr.s_node = sat->sat_addr.s_node;
380
* Make sure any route that we have has a valid interface.
383
if ( ro->ro_rt && ( ifp = ro->ro_rt->rt_ifp )) {
384
for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
385
if ( aa->aa_ifp == ifp ) {
391
return( ENETUNREACH );
394
ddp->ddp_fsat = *sat;
395
if ( ddp->ddp_lsat.sat_port == ATADDR_ANYPORT ) {
396
return( at_pcbsetaddr( ddp, (struct mbuf *)0 ));
401
at_pcbdisconnect( ddp )
404
ddp->ddp_fsat.sat_addr.s_net = ATADDR_ANYNET;
405
ddp->ddp_fsat.sat_addr.s_node = ATADDR_ANYNODE;
406
ddp->ddp_fsat.sat_port = ATADDR_ANYPORT;
415
m = m_getclr( M_WAIT, MT_PCB );
416
ddp = mtod( m, struct ddpcb * );
417
ddp->ddp_lsat.sat_port = ATADDR_ANYPORT;
419
ddp->ddp_next = ddpcb;
420
ddp->ddp_prev = NULL;
421
ddp->ddp_pprev = NULL;
422
ddp->ddp_pnext = NULL;
424
ddpcb->ddp_prev = ddp;
428
ddp->ddp_socket = so;
429
so->so_pcb = (caddr_t)ddp;
433
at_pcbdetach( so, ddp )
437
soisdisconnected( so );
441
/* remove ddp from ddp_ports list */
442
if ( ddp->ddp_lsat.sat_port != ATADDR_ANYPORT &&
443
ddp_ports[ ddp->ddp_lsat.sat_port - 1 ] != NULL ) {
444
if ( ddp->ddp_pprev != NULL ) {
445
ddp->ddp_pprev->ddp_pnext = ddp->ddp_pnext;
447
ddp_ports[ ddp->ddp_lsat.sat_port - 1 ] = ddp->ddp_pnext;
449
if ( ddp->ddp_pnext != NULL ) {
450
ddp->ddp_pnext->ddp_pprev = ddp->ddp_pprev;
454
if ( ddp->ddp_route.ro_rt ) {
455
rtfree( ddp->ddp_route.ro_rt );
458
if ( ddp->ddp_prev ) {
459
ddp->ddp_prev->ddp_next = ddp->ddp_next;
461
ddpcb = ddp->ddp_next;
463
if ( ddp->ddp_next ) {
464
ddp->ddp_next->ddp_prev = ddp->ddp_prev;
467
(void) m_free( dtom( ddp ));
471
* For the moment, this just find the pcb with the correct local address.
472
* In the future, this will actually do some real searching, so we can use
473
* the sender's address to do de-multiplexing on a single port to many
477
ddp_search( from, to, aa )
478
struct sockaddr_at *from, *to;
479
struct at_ifaddr *aa;
484
* Check for bad ports.
486
if ( to->sat_port < ATPORT_FIRST || to->sat_port >= ATPORT_LAST ) {
491
* Make sure the local address matches the sent address. What about
494
for ( ddp = ddp_ports[ to->sat_port - 1 ]; ddp; ddp = ddp->ddp_pnext ) {
495
/* XXX should we handle 0.YY? */
497
/* XXXX.YY to socket on destination interface */
498
if ( to->sat_addr.s_net == ddp->ddp_lsat.sat_addr.s_net &&
499
to->sat_addr.s_node == ddp->ddp_lsat.sat_addr.s_node ) {
503
/* 0.255 to socket on receiving interface */
504
if ( to->sat_addr.s_node == ATADDR_BCAST && ( to->sat_addr.s_net == 0 ||
505
to->sat_addr.s_net == ddp->ddp_lsat.sat_addr.s_net ) &&
506
ddp->ddp_lsat.sat_addr.s_net == AA_SAT( aa )->sat_addr.s_net ) {
510
/* XXXX.0 to socket on destination interface */
511
if ( to->sat_addr.s_net == aa->aa_firstnet &&
512
to->sat_addr.s_node == 0 &&
513
ntohs( ddp->ddp_lsat.sat_addr.s_net ) >=
514
ntohs( aa->aa_firstnet ) &&
515
ntohs( ddp->ddp_lsat.sat_addr.s_net ) <=
516
ntohs( aa->aa_lastnet )) {
525
atintrq1.ifq_maxlen = IFQ_MAXLEN;
526
atintrq2.ifq_maxlen = IFQ_MAXLEN;
533
for ( ddp = ddpcb; ddp; ddp = ddp->ddp_next ) {
534
at_pcbdetach( ddp->ddp_socket, ddp );