2 * Copyright (c) 1990,1994 Regents of The University of Michigan.
3 * All Rights Reserved. See COPYRIGHT.
5 * $DragonFly: src/sys/netproto/atalk/ddp_usrreq.c,v 1.14 2008/09/24 14:26:39 sephe Exp $
12 #include <sys/malloc.h>
14 #include <sys/socket.h>
15 #include <sys/socketvar.h>
16 #include <sys/protosw.h>
17 #include <sys/thread2.h>
19 #include <net/netisr.h>
20 #include <net/route.h>
25 #include "at_extern.h"
27 static void at_pcbdisconnect( struct ddpcb
*ddp
);
28 static void at_sockaddr(struct ddpcb
*ddp
, struct sockaddr
**addr
);
29 static int at_pcbsetaddr(struct ddpcb
*ddp
, struct sockaddr
*addr
,
31 static int at_pcbconnect(struct ddpcb
*ddp
, struct sockaddr
*addr
,
33 static void at_pcbdetach(struct socket
*so
, struct ddpcb
*ddp
);
34 static int at_pcballoc(struct socket
*so
);
36 struct ddpcb
*ddp_ports
[ ATPORT_LAST
];
37 struct ddpcb
*ddpcb
= NULL
;
38 static u_long ddp_sendspace
= DDP_MAXSZ
; /* Max ddp size + 1 (ddp_type) */
39 static u_long ddp_recvspace
= 10 * ( 587 + sizeof( struct sockaddr_at
));
42 ddp_attach(struct socket
*so
, int proto
, struct pru_attach_info
*ai
)
48 ddp
= sotoddpcb( so
);
54 error
= at_pcballoc( so
);
59 return (soreserve( so
, ddp_sendspace
, ddp_recvspace
, ai
->sb_rlimit
));
63 ddp_detach(struct socket
*so
)
67 ddp
= sotoddpcb( so
);
72 at_pcbdetach( so
, ddp
);
78 ddp_bind(struct socket
*so
, struct sockaddr
*nam
, struct thread
*td
)
83 ddp
= sotoddpcb( so
);
88 error
= at_pcbsetaddr(ddp
, nam
, td
);
94 ddp_connect(struct socket
*so
, struct sockaddr
*nam
, struct thread
*td
)
99 ddp
= sotoddpcb( so
);
104 if ( ddp
->ddp_fsat
.sat_port
!= ATADDR_ANYPORT
) {
109 error
= at_pcbconnect( ddp
, nam
, td
);
117 ddp_disconnect(struct socket
*so
)
122 ddp
= sotoddpcb( so
);
126 if ( ddp
->ddp_fsat
.sat_addr
.s_node
== ATADDR_ANYNODE
) {
131 at_pcbdisconnect( ddp
);
132 ddp
->ddp_fsat
.sat_addr
.s_node
= ATADDR_ANYNODE
;
134 soisdisconnected( so
);
139 ddp_shutdown(struct socket
*so
)
143 ddp
= sotoddpcb( so
);
147 socantsendmore( so
);
152 ddp_send(struct socket
*so
, int flags
, struct mbuf
*m
, struct sockaddr
*addr
,
153 struct mbuf
*control
, struct thread
*td
)
158 ddp
= sotoddpcb( so
);
163 if ( control
&& control
->m_len
) {
168 if ( ddp
->ddp_fsat
.sat_port
!= ATADDR_ANYPORT
) {
173 error
= at_pcbconnect(ddp
, addr
, td
);
179 if ( ddp
->ddp_fsat
.sat_port
== ATADDR_ANYPORT
) {
185 error
= ddp_output( m
, so
);
187 at_pcbdisconnect( ddp
);
194 ddp_abort(struct socket
*so
)
198 ddp
= sotoddpcb( so
);
202 soisdisconnected( so
);
204 at_pcbdetach( so
, ddp
);
211 at_sockaddr(struct ddpcb
*ddp
, struct sockaddr
**addr
)
213 *addr
= dup_sockaddr((struct sockaddr
*)&ddp
->ddp_lsat
);
217 at_pcbsetaddr(struct ddpcb
*ddp
, struct sockaddr
*addr
, struct thread
*td
)
219 struct sockaddr_at lsat
, *sat
;
220 struct at_ifaddr
*aa
;
223 if ( ddp
->ddp_lsat
.sat_port
!= ATADDR_ANYPORT
) { /* shouldn't be bound */
227 if (addr
!= 0) { /* validate passed address */
228 sat
= (struct sockaddr_at
*)addr
;
229 if (sat
->sat_family
!= AF_APPLETALK
) {
230 return(EAFNOSUPPORT
);
233 if ( sat
->sat_addr
.s_node
!= ATADDR_ANYNODE
||
234 sat
->sat_addr
.s_net
!= ATADDR_ANYNET
) {
235 for ( aa
= at_ifaddr
; aa
; aa
= aa
->aa_next
) {
236 if (( sat
->sat_addr
.s_net
== AA_SAT( aa
)->sat_addr
.s_net
) &&
237 ( sat
->sat_addr
.s_node
== AA_SAT( aa
)->sat_addr
.s_node
)) {
242 return( EADDRNOTAVAIL
);
246 if ( sat
->sat_port
!= ATADDR_ANYPORT
) {
247 if ( sat
->sat_port
< ATPORT_FIRST
||
248 sat
->sat_port
>= ATPORT_LAST
) {
251 if ( sat
->sat_port
< ATPORT_RESERVED
&&
252 priv_check(td
, PRIV_ROOT
) ) {
257 bzero( (caddr_t
)&lsat
, sizeof( struct sockaddr_at
));
258 lsat
.sat_len
= sizeof(struct sockaddr_at
);
259 lsat
.sat_addr
.s_node
= ATADDR_ANYNODE
;
260 lsat
.sat_addr
.s_net
= ATADDR_ANYNET
;
261 lsat
.sat_family
= AF_APPLETALK
;
265 if ( sat
->sat_addr
.s_node
== ATADDR_ANYNODE
&&
266 sat
->sat_addr
.s_net
== ATADDR_ANYNET
) {
267 if ( at_ifaddr
== NULL
) {
268 return( EADDRNOTAVAIL
);
270 sat
->sat_addr
= AA_SAT( at_ifaddr
)->sat_addr
;
272 ddp
->ddp_lsat
= *sat
;
277 if ( sat
->sat_port
== ATADDR_ANYPORT
) {
278 for ( sat
->sat_port
= ATPORT_RESERVED
;
279 sat
->sat_port
< ATPORT_LAST
; sat
->sat_port
++ ) {
280 if ( ddp_ports
[ sat
->sat_port
- 1 ] == 0 ) {
284 if ( sat
->sat_port
== ATPORT_LAST
) {
285 return( EADDRNOTAVAIL
);
287 ddp
->ddp_lsat
.sat_port
= sat
->sat_port
;
288 ddp_ports
[ sat
->sat_port
- 1 ] = ddp
;
290 for ( ddpp
= ddp_ports
[ sat
->sat_port
- 1 ]; ddpp
;
291 ddpp
= ddpp
->ddp_pnext
) {
292 if ( ddpp
->ddp_lsat
.sat_addr
.s_net
== sat
->sat_addr
.s_net
&&
293 ddpp
->ddp_lsat
.sat_addr
.s_node
== sat
->sat_addr
.s_node
) {
297 if ( ddpp
!= NULL
) {
298 return( EADDRINUSE
);
300 ddp
->ddp_pnext
= ddp_ports
[ sat
->sat_port
- 1 ];
301 ddp_ports
[ sat
->sat_port
- 1 ] = ddp
;
302 if ( ddp
->ddp_pnext
) {
303 ddp
->ddp_pnext
->ddp_pprev
= ddp
;
311 at_pcbconnect(struct ddpcb
*ddp
, struct sockaddr
*addr
, struct thread
*td
)
313 struct sockaddr_at
*sat
= (struct sockaddr_at
*)addr
;
315 struct at_ifaddr
*aa
= 0;
317 u_short hintnet
= 0, net
;
319 if (sat
->sat_family
!= AF_APPLETALK
) {
320 return(EAFNOSUPPORT
);
324 * Under phase 2, network 0 means "the network". We take "the
325 * network" to mean the network the control block is bound to.
326 * If the control block is not bound, there is an error.
328 if ( sat
->sat_addr
.s_net
== ATADDR_ANYNET
329 && sat
->sat_addr
.s_node
!= ATADDR_ANYNODE
) {
330 if ( ddp
->ddp_lsat
.sat_port
== ATADDR_ANYPORT
) {
331 return( EADDRNOTAVAIL
);
333 hintnet
= ddp
->ddp_lsat
.sat_addr
.s_net
;
336 ro
= &ddp
->ddp_route
;
338 * If we've got an old route for this pcb, check that it is valid.
339 * If we've changed our address, we may have an old "good looking"
340 * route here. Attempt to detect it.
346 net
= sat
->sat_addr
.s_net
;
349 if ((ifp
= ro
->ro_rt
->rt_ifp
) != NULL
) {
350 for ( aa
= at_ifaddr
; aa
; aa
= aa
->aa_next
) {
351 if ( aa
->aa_ifp
== ifp
&&
352 ntohs( net
) >= ntohs( aa
->aa_firstnet
) &&
353 ntohs( net
) <= ntohs( aa
->aa_lastnet
)) {
358 if ( aa
== NULL
|| ( satosat( &ro
->ro_dst
)->sat_addr
.s_net
!=
359 ( hintnet
? hintnet
: sat
->sat_addr
.s_net
) ||
360 satosat( &ro
->ro_dst
)->sat_addr
.s_node
!=
361 sat
->sat_addr
.s_node
)) {
368 * If we've got no route for this interface, try to find one.
370 if ( ro
->ro_rt
== NULL
||
371 ro
->ro_rt
->rt_ifp
== NULL
) {
372 ro
->ro_dst
.sa_len
= sizeof( struct sockaddr_at
);
373 ro
->ro_dst
.sa_family
= AF_APPLETALK
;
375 satosat( &ro
->ro_dst
)->sat_addr
.s_net
= hintnet
;
377 satosat( &ro
->ro_dst
)->sat_addr
.s_net
= sat
->sat_addr
.s_net
;
379 satosat( &ro
->ro_dst
)->sat_addr
.s_node
= sat
->sat_addr
.s_node
;
384 * Make sure any route that we have has a valid interface.
387 if ( ro
->ro_rt
&& ( ifp
= ro
->ro_rt
->rt_ifp
)) {
388 for ( aa
= at_ifaddr
; aa
; aa
= aa
->aa_next
) {
389 if ( aa
->aa_ifp
== ifp
) {
395 return( ENETUNREACH
);
398 ddp
->ddp_fsat
= *sat
;
399 if ( ddp
->ddp_lsat
.sat_port
== ATADDR_ANYPORT
) {
400 return(at_pcbsetaddr(ddp
, NULL
, td
));
406 at_pcbdisconnect( struct ddpcb
*ddp
)
408 ddp
->ddp_fsat
.sat_addr
.s_net
= ATADDR_ANYNET
;
409 ddp
->ddp_fsat
.sat_addr
.s_node
= ATADDR_ANYNODE
;
410 ddp
->ddp_fsat
.sat_port
= ATADDR_ANYPORT
;
414 at_pcballoc( struct socket
*so
)
418 MALLOC(ddp
, struct ddpcb
*, sizeof *ddp
, M_PCB
, M_WAITOK
| M_ZERO
);
419 ddp
->ddp_lsat
.sat_port
= ATADDR_ANYPORT
;
421 ddp
->ddp_next
= ddpcb
;
422 ddp
->ddp_prev
= NULL
;
423 ddp
->ddp_pprev
= NULL
;
424 ddp
->ddp_pnext
= NULL
;
426 ddpcb
->ddp_prev
= ddp
;
430 ddp
->ddp_socket
= so
;
431 so
->so_pcb
= (caddr_t
)ddp
;
436 at_pcbdetach( struct socket
*so
, struct ddpcb
*ddp
)
438 soisdisconnected( so
);
442 /* remove ddp from ddp_ports list */
443 if ( ddp
->ddp_lsat
.sat_port
!= ATADDR_ANYPORT
&&
444 ddp_ports
[ ddp
->ddp_lsat
.sat_port
- 1 ] != NULL
) {
445 if ( ddp
->ddp_pprev
!= NULL
) {
446 ddp
->ddp_pprev
->ddp_pnext
= ddp
->ddp_pnext
;
448 ddp_ports
[ ddp
->ddp_lsat
.sat_port
- 1 ] = ddp
->ddp_pnext
;
450 if ( ddp
->ddp_pnext
!= NULL
) {
451 ddp
->ddp_pnext
->ddp_pprev
= ddp
->ddp_pprev
;
455 if ( ddp
->ddp_route
.ro_rt
) {
456 rtfree( ddp
->ddp_route
.ro_rt
);
459 if ( ddp
->ddp_prev
) {
460 ddp
->ddp_prev
->ddp_next
= ddp
->ddp_next
;
462 ddpcb
= ddp
->ddp_next
;
464 if ( ddp
->ddp_next
) {
465 ddp
->ddp_next
->ddp_prev
= ddp
->ddp_prev
;
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( struct sockaddr_at
*from
, struct sockaddr_at
*to
,
478 struct at_ifaddr
*aa
)
483 * Check for bad ports.
485 if ( to
->sat_port
< ATPORT_FIRST
|| to
->sat_port
>= ATPORT_LAST
) {
490 * Make sure the local address matches the sent address. What about
493 for ( ddp
= ddp_ports
[ to
->sat_port
- 1 ]; ddp
; ddp
= ddp
->ddp_pnext
) {
494 /* XXX should we handle 0.YY? */
496 /* XXXX.YY to socket on destination interface */
497 if ( to
->sat_addr
.s_net
== ddp
->ddp_lsat
.sat_addr
.s_net
&&
498 to
->sat_addr
.s_node
== ddp
->ddp_lsat
.sat_addr
.s_node
) {
502 /* 0.255 to socket on receiving interface */
503 if ( to
->sat_addr
.s_node
== ATADDR_BCAST
&& ( to
->sat_addr
.s_net
== 0 ||
504 to
->sat_addr
.s_net
== ddp
->ddp_lsat
.sat_addr
.s_net
) &&
505 ddp
->ddp_lsat
.sat_addr
.s_net
== AA_SAT( aa
)->sat_addr
.s_net
) {
509 /* XXXX.0 to socket on destination interface */
510 if ( to
->sat_addr
.s_net
== aa
->aa_firstnet
&&
511 to
->sat_addr
.s_node
== 0 &&
512 ntohs( ddp
->ddp_lsat
.sat_addr
.s_net
) >=
513 ntohs( aa
->aa_firstnet
) &&
514 ntohs( ddp
->ddp_lsat
.sat_addr
.s_net
) <=
515 ntohs( aa
->aa_lastnet
)) {
522 at_setpeeraddr(struct socket
*so
, struct sockaddr
**nam
)
528 at_setsockaddr(struct socket
*so
, struct sockaddr
**nam
)
532 ddp
= sotoddpcb( so
);
536 at_sockaddr( ddp
, nam
);
544 netisr_register(NETISR_ATALK1
, cpu0_portfn
, pktinfo_portfn_cpu0
,
545 at1intr
, NETISR_FLAG_NOTMPSAFE
);
546 netisr_register(NETISR_ATALK2
, cpu0_portfn
, pktinfo_portfn_cpu0
,
547 at2intr
, NETISR_FLAG_NOTMPSAFE
);
548 netisr_register(NETISR_AARP
, cpu0_portfn
, pktinfo_portfn_cpu0
,
549 aarpintr
, NETISR_FLAG_NOTMPSAFE
);
558 for ( ddp
= ddpcb
; ddp
; ddp
= ddp
->ddp_next
) {
559 at_pcbdetach( ddp
->ddp_socket
, ddp
);
564 struct pr_usrreqs ddp_usrreqs
= {
565 .pru_abort
= ddp_abort
,
566 .pru_accept
= pru_accept_notsupp
,
567 .pru_attach
= ddp_attach
,
568 .pru_bind
= ddp_bind
,
569 .pru_connect
= ddp_connect
,
570 .pru_connect2
= pru_connect2_notsupp
,
571 .pru_control
= at_control
,
572 .pru_detach
= ddp_detach
,
573 .pru_disconnect
= ddp_disconnect
,
574 .pru_listen
= pru_listen_notsupp
,
575 .pru_peeraddr
= at_setpeeraddr
,
576 .pru_rcvd
= pru_rcvd_notsupp
,
577 .pru_rcvoob
= pru_rcvoob_notsupp
,
578 .pru_send
= ddp_send
,
579 .pru_sense
= pru_sense_null
,
580 .pru_shutdown
= ddp_shutdown
,
581 .pru_sockaddr
= at_setsockaddr
,
582 .pru_sosend
= sosend
,
583 .pru_soreceive
= soreceive
,