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