1/* 2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/* 29 * Copyright (c) 1996 Apple Computer, Inc. 30 * 31 * Created April 8, 1996 by Tuyen Nguyen 32 * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX. 33 * 34 * File: open.c 35 */ 36 37#ifdef AURP_SUPPORT 38 39#include <sys/errno.h> 40#include <sys/types.h> 41#include <sys/param.h> 42#include <machine/spl.h> 43#include <sys/systm.h> 44#include <sys/kernel.h> 45#include <sys/proc.h> 46#include <sys/filedesc.h> 47#include <sys/fcntl.h> 48#include <sys/mbuf.h> 49#include <sys/socket.h> 50#include <sys/socketvar.h> 51#include <net/if.h> 52 53#include <netat/sysglue.h> 54#include <netat/appletalk.h> 55#include <netat/at_pcb.h> 56#include <netat/at_var.h> 57#include <netat/routing_tables.h> 58#include <netat/aurp.h> 59#include <netat/debug.h> 60 61 62/* locked version of AURPsndOpenReq */ 63void AURPsndOpenReq_locked(state) 64 aurp_state_t *state; 65{ 66 atalk_lock(); 67 AURPsndOpenReq(state); 68 atalk_unlock(); 69} 70 71/* */ 72void AURPsndOpenReq(state) 73 aurp_state_t *state; 74{ 75 int msize; 76 gbuf_t *m; 77 aurp_hdr_t *hdrp; 78 79 if (aurp_gref == 0) { 80 return; 81 } 82 if (state->rcv_retry && (state->rcv_state != AURPSTATE_WaitingForOpenRsp)) { 83 return; 84 } 85 86 /* stop trying if the retry count exceeds the maximum value */ 87 if (++state->rcv_retry > AURP_MaxRetry) { 88 dPrintf(D_M_AURP, D_L_WARNING, 89 ("AURPsndOpenReq: no response, node %u\n", 90 state->rem_node)); 91 state->rcv_state = AURPSTATE_Unconnected; 92 state->rcv_tmo = 0; 93 state->rcv_retry = 0; 94 return; 95 } 96 97 msize = sizeof(aurp_hdr_t) + 3; 98 if ((m = (gbuf_t *)gbuf_alloc(msize, PRI_MED)) != 0) { 99 gbuf_wset(m,msize); 100 101 /* construct the open request packet */ 102 hdrp = (aurp_hdr_t *)gbuf_rptr(m); 103 if (state->rcv_retry > 1) 104 hdrp->connection_id = state->rcv_connection_id; 105 else { 106 if (++rcv_connection_id == 0) 107 rcv_connection_id = 1; 108 hdrp->connection_id = rcv_connection_id; 109 } 110 hdrp->sequence_number = 0; 111 hdrp->command_code = AURPCMD_OpenReq; 112 hdrp->flags = (AURPFLG_NA | AURPFLG_ND | AURPFLG_NDC | AURPFLG_ZC); 113 *(short *)(hdrp+1) = AURP_Version; 114 ((char *)(hdrp+1))[2] = 0; /* option count */ 115 116 /* update state info */ 117 state->rcv_connection_id = hdrp->connection_id; 118 state->rcv_state = AURPSTATE_WaitingForOpenRsp; 119 120 /* send the packet */ 121 dPrintf(D_M_AURP, D_L_TRACE, 122 ("AURPsndOpenReq: sending AURPCMD_OpenReq, node %u\n", 123 state->rem_node)); 124 AURPsend(m, AUD_AURP, state->rem_node); 125 } 126 127 /* start the retry timer */ 128 timeout(AURPsndOpenReq_locked, state, AURP_RetryInterval*HZ); 129 state->rcv_tmo = 1; 130} 131 132/* */ 133void AURPrcvOpenReq(state, m) 134 aurp_state_t *state; 135 gbuf_t *m; 136{ 137 short rc, version; 138 aurp_hdr_t *hdrp = (aurp_hdr_t *)gbuf_rptr(m); 139 unsigned short sui = hdrp->flags; 140 141 /* make sure we're in a valid state to accept it */ 142 if ((update_tmo == 0) || ((state->snd_state != AURPSTATE_Unconnected) && 143 (state->snd_state != AURPSTATE_Connected))) { 144 dPrintf(D_M_AURP, D_L_WARNING, 145 ("AURPrcvOpenReq: unexpected request, update_tmo=0x%x, snd_state=%u\n", (unsigned int) update_tmo, state->snd_state)); 146 gbuf_freem(m); 147 return; 148 } 149 150 /* check for the correct version number */ 151 version = *(short *)(hdrp+1); 152 if (version != AURP_Version) { 153 dPrintf(D_M_AURP, D_L_WARNING, 154 ("AURPrcvOpenReq: invalid version number %d, expected %d\n", version, AURP_Version)); 155 rc = AURPERR_InvalidVersionNumber; 156 } else 157 rc = (short)AURP_UpdateRate; 158 159 /* construct the open response packet */ 160 gbuf_wset(m,sizeof(aurp_hdr_t)+sizeof(short)); 161 hdrp->command_code = AURPCMD_OpenRsp; 162 hdrp->flags = 0; 163 *(short *)(hdrp+1) = rc; 164 ((char *)(hdrp+1))[2] = 0; /* option count */ 165 166 /* 167 * reset if we're in the Connected state and this is 168 * a completely new open request 169 */ 170 if ((state->snd_state == AURPSTATE_Connected) && 171 ((state->snd_connection_id != hdrp->connection_id) || 172 (state->snd_sequence_number != AURP_FirstSeqNum))) { 173 extern void AURPsndTickle(); 174 if (state->rcv_state == AURPSTATE_Connected) { 175 state->rcv_state = AURPSTATE_Unconnected; 176 untimeout(AURPsndTickle, state); 177 } 178 state->snd_state = AURPSTATE_Unconnected; 179 AURPcleanup(state); 180 AURPpurgeri(state->rem_node); 181 } 182 183 /* update state info */ 184 if (state->snd_state == AURPSTATE_Unconnected) { 185 state->snd_state = AURPSTATE_Connected; 186 state->snd_sui = sui; 187 state->snd_connection_id = hdrp->connection_id; 188 state->snd_sequence_number = AURP_FirstSeqNum; 189 } 190 191 /* send the packet */ 192 AURPsend(m, AUD_AURP, state->rem_node); 193 194 /* open connection for the data receiver side if not yet connected */ 195 if (state->rcv_state == AURPSTATE_Unconnected) { 196 state->rcv_retry = 0; 197 state->tickle_retry = 0; 198 state->rcv_sequence_number = 0; 199 AURPsndOpenReq(state); 200 } 201} 202 203/* */ 204void AURPrcvOpenRsp(state, m) 205 aurp_state_t *state; 206 gbuf_t *m; 207{ 208 extern void AURPsndTickle(); 209 short rc; 210 aurp_hdr_t *hdrp = (aurp_hdr_t *)gbuf_rptr(m); 211 212 /* make sure we're in a valid state to accept it */ 213 if (state->rcv_state != AURPSTATE_WaitingForOpenRsp) { 214 dPrintf(D_M_AURP, D_L_WARNING, 215 ("AURPrcvOpenRsp: unexpected response\n")); 216 gbuf_freem(m); 217 return; 218 } 219 220 /* check for the correct connection id */ 221 if (hdrp->connection_id != state->rcv_connection_id) { 222 dPrintf(D_M_AURP, D_L_WARNING, 223 ("AURPrcvOpenRsp: invalid connection id, r=%d, m=%d\n", 224 hdrp->connection_id, state->rcv_connection_id)); 225 gbuf_freem(m); 226 return; 227 } 228 229 /* cancel the retry timer */ 230 untimeout(AURPsndOpenReq_locked, state); 231 state->rcv_tmo = 0; 232 state->rcv_retry = 0; 233 234 /* update state info */ 235 state->rcv_sequence_number = AURP_FirstSeqNum; 236 state->rcv_env = hdrp->flags; 237 238 /* check for error */ 239 rc = *(short *)(hdrp+1); 240 gbuf_freem(m); 241 if (rc < 0) { 242 dPrintf(D_M_AURP, D_L_WARNING, 243 ("AURPrcvOpenRsp: error=%d\n", rc)); 244 return; 245 } 246 247 /* update state info */ 248 state->rcv_update_rate = (unsigned short)rc; 249 state->rcv_state = AURPSTATE_Connected; 250 dPrintf(D_M_AURP, D_L_TRACE, ("AURPrcvOpenRsp: moved rcv_state to AURPSTATE_Connected\n")); 251 252 /* start tickle */ 253 timeout(AURPsndTickle, state, AURP_TickleRetryInterval*HZ); 254 255 /* get routing info */ 256 AURPsndRIReq(state); 257} 258 259#endif /* AURP_SUPPORT */ 260