]> arthur.barton.de Git - netatalk.git/blob - sys/solaris/sock.c
Initial revision
[netatalk.git] / sys / solaris / sock.c
1 #include <sys/types.h>
2 #include <sys/stream.h>
3 #include <sys/socket.h>
4 #include <sys/errno.h>
5 #include <sys/kmem.h>
6 #include <sys/cmn_err.h>
7 #include <sys/tihdr.h>
8 #include <sys/ethernet.h>
9 #include <net/if.h>
10
11 #include <string.h>
12
13 #include <netatalk/at.h>
14
15 #include "if.h"
16 #include "sock.h"
17
18 static struct sock_data *sockets = NULL;
19
20     struct sock_data *
21 sock_alloc( queue_t *q )
22 {
23     struct sock_data    *sd;
24
25     if (( sd = kmem_alloc( sizeof( struct sock_data ), KM_SLEEP )) == NULL ) {
26         return( NULL );
27     }
28     sd->sd_state = TS_UNBND;
29     sd->sd_q = q;
30     sd->sd_next = sd->sd_prev = NULL;
31     bzero( (caddr_t)&sd->sd_sat, sizeof( struct sockaddr_at ));
32
33     sd->sd_next = sockets;
34     if ( sockets != NULL ) {
35         sockets->sd_prev = sd;
36     }
37     sockets = sd;
38
39     return( sd );
40 }
41
42     void
43 sock_free( struct sock_data *sd )
44 {
45     if ( sd == sockets ) {
46         sockets = sd->sd_next;
47     }
48     if ( sd->sd_next != NULL ) {
49         sd->sd_next->sd_prev = sd->sd_prev;
50     }
51     if ( sd->sd_prev != NULL ) {
52         sd->sd_prev->sd_next = sd->sd_next;
53     }
54     kmem_free( sd, sizeof( struct sock_data ));
55     return;
56 }
57
58     struct sock_data *
59 sock_dest( struct atif_data *aid, struct sockaddr_at *sat )
60 {
61     struct sock_data    *sd;
62
63     for ( sd = sockets; sd != NULL; sd = sd->sd_next ) {
64         if ( sat->sat_port == sd->sd_sat.sat_port &&
65                 /* huh? */
66                 aid->aid_sat.sat_addr.s_net == sd->sd_sat.sat_addr.s_net &&
67                 ( sat->sat_addr.s_node == sd->sd_sat.sat_addr.s_node ||
68                 sat->sat_addr.s_node == ATADDR_BCAST )) {
69             break;
70         }
71     }
72     return( sd );
73 }
74
75 /*
76  * This is a change in semantics.  The port must be ATADDR_ANYPORT for
77  * ATADDR_ANYNET/NODE to not mean the loopback.
78  */
79     int
80 sock_bind( struct sock_data *sd, struct sockaddr_at *sat )
81 {
82     struct atif_data    *paid;
83     struct sock_data    *psd;
84     struct sockaddr_at  psat;
85     u_short             port;
86
87     psat = *sat;
88     if ( psat.sat_family != AF_APPLETALK ) {
89         cmn_err( CE_CONT, "sock_bind non-AppleTalk\n" );
90         return( EPROTOTYPE );
91     }
92
93     if ( psat.sat_port == ATADDR_ANYPORT ) {
94         if ( psat.sat_addr.s_net == ATADDR_ANYNET &&
95                 psat.sat_addr.s_node == ATADDR_ANYNODE ) {
96             /* chose primary interface */
97             if (( paid = if_primary()) == NULL ) {
98                 return( EADDRNOTAVAIL );
99             }
100             psat.sat_addr.s_net = paid->aid_sat.sat_addr.s_net;
101             psat.sat_addr.s_node = paid->aid_sat.sat_addr.s_node;
102         }
103
104         /* pick unused port */
105         for ( port = ATPORT_RESERVED; port < ATPORT_LAST; port++ ) {
106             for ( psd = sockets; psd != NULL; psd = psd->sd_next ) {
107                 if ( port == psd->sd_sat.sat_port &&
108                         psat.sat_addr.s_net == psd->sd_sat.sat_addr.s_net &&
109                         psat.sat_addr.s_node == psd->sd_sat.sat_addr.s_node ) {
110                     break;
111                 }
112             }
113             if ( psd == NULL ) {
114                 break;
115             }
116         }
117         if ( psd != NULL ) {
118             return( EADDRINUSE );
119         }
120         psat.sat_port = port;
121     }
122
123     sd->sd_sat = psat;
124     sd->sd_state = TS_IDLE;
125     return( 0 );
126 }