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