kernel tree reorganization stage 1: Major cvs repository work (not logged as
[dragonfly.git] / sys / netproto / atm / uni / uniarp_vcm.c
CommitLineData
984263bc
MD
1/*
2 *
3 * ===================================
4 * HARP | Host ATM Research Platform
5 * ===================================
6 *
7 *
8 * This Host ATM Research Platform ("HARP") file (the "Software") is
9 * made available by Network Computing Services, Inc. ("NetworkCS")
10 * "AS IS". NetworkCS does not provide maintenance, improvements or
11 * support of any kind.
12 *
13 * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
14 * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
15 * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
16 * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
17 * In no event shall NetworkCS be responsible for any damages, including
18 * but not limited to consequential damages, arising from or relating to
19 * any use of the Software or related support.
20 *
21 * Copyright 1994-1998 Network Computing Services, Inc.
22 *
23 * Copies of this Software may be made, however, the above copyright
24 * notice must be reproduced on all copies.
25 *
26 * @(#) $FreeBSD: src/sys/netatm/uni/uniarp_vcm.c,v 1.5 2000/01/17 20:49:55 mks Exp $
d2438d69 27 * @(#) $DragonFly: src/sys/netproto/atm/uni/uniarp_vcm.c,v 1.4 2003/08/07 21:54:34 dillon Exp $
984263bc
MD
28 */
29
30/*
31 * ATM Forum UNI Support
32 * ---------------------
33 *
34 * UNI ATMARP support (RFC1577) - Virtual Channel Management
35 *
36 */
37
d2438d69 38#include <netproto/atm/kern_include.h>
984263bc 39
d2438d69
MD
40#include <netproto/atm/ipatm/ipatm_var.h>
41#include <netproto/atm/ipatm/ipatm_serv.h>
1f2de5d4 42#include "uniip_var.h"
984263bc 43
984263bc
MD
44/*
45 * Local variables
46 */
47static struct attr_llc uniarp_llc = {
48 T_ATM_PRESENT,
49 {
50 T_ATM_LLC_SHARING,
51 8,
52 {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x08, 0x06}
53 }
54};
55
56static struct t_atm_cause uniarp_cause = {
57 T_ATM_ITU_CODING,
58 T_ATM_LOC_USER,
59 T_ATM_CAUSE_TEMPORARY_FAILURE,
60 {0, 0, 0, 0}
61};
62
63
64/*
65 * Process a new PVC requiring ATMARP support
66 *
67 * This function is called after IP/ATM has successfully opened a PVC which
68 * requires ATMARP support. We will send an InATMARP request over the PVC
69 * to elicit a response from the PVC's ATMARP peer informing us of its
70 * network address. This information will also be used by IP/ATM in order
71 * to complete its address-to-VC mapping table.
72 *
73 * Arguments:
74 * ivp pointer to PVC's IPVCC control block
75 *
76 * Returns:
77 * MAP_PROCEEDING - OK so far, querying for peer's mapping
78 * MAP_FAILED - error, unable to allocate resources
79 *
80 */
81int
82uniarp_pvcopen(ivp)
83 struct ipvcc *ivp;
84{
85 struct uniip *uip;
86 struct uniarp *uap;
87 int s, err;
88
89 ATM_DEBUG1("uniarp_pvcopen: ivp=%p\n", ivp);
90
91 ivp->iv_arpent = NULL;
92
93 /*
94 * Check things out
95 */
96 if ((ivp->iv_flags & IVF_LLC) == 0)
97 return (MAP_FAILED);
98
99 /*
100 * Get uni interface
101 */
102 uip = (struct uniip *)ivp->iv_ipnif->inf_isintf;
103 if (uip == NULL)
104 return (MAP_FAILED);
105
106 /*
107 * Get an arp map entry
108 */
109 uap = (struct uniarp *)atm_allocate(&uniarp_pool);
110 if (uap == NULL)
111 return (MAP_FAILED);
112
113 /*
114 * Create our CM connection
115 */
116 err = atm_cm_addllc(&uniarp_endpt, ivp, &uniarp_llc,
117 ivp->iv_conn, &ivp->iv_arpconn);
118 if (err) {
119 /*
120 * We don't take no (or maybe) for an answer
121 */
122 if (ivp->iv_arpconn) {
123 (void) atm_cm_release(ivp->iv_arpconn, &uniarp_cause);
124 ivp->iv_arpconn = NULL;
125 }
126 atm_free((caddr_t)uap);
127 return (MAP_FAILED);
128 }
129
130 /*
131 * Get map entry set up
132 */
133 s = splnet();
134 uap->ua_dstatm.address_format = T_ATM_ABSENT;
135 uap->ua_dstatmsub.address_format = T_ATM_ABSENT;
136 uap->ua_intf = uip;
137
138 /*
139 * Put ivp on arp entry chain
140 */
141 LINK2TAIL(ivp, struct ipvcc, uap->ua_ivp, iv_arpnext);
142 ivp->iv_arpent = (struct arpmap *)uap;
143
144 /*
145 * Put arp entry on pvc chain
146 */
147 LINK2TAIL(uap, struct uniarp, uniarp_pvctab, ua_next);
148
149 /*
150 * Send Inverse ATMARP request
151 */
152 (void) uniarp_inarp_req(uip, &uap->ua_dstatm, &uap->ua_dstatmsub, ivp);
153
154 /*
155 * Start resend timer
156 */
157 uap->ua_aging = UNIARP_REVALID_AGE;
158
159 (void) splx(s);
160 return (MAP_PROCEEDING);
161}
162
163
164/*
165 * Process a new outgoing SVC requiring ATMARP support
166 *
167 * This function is called by the IP/ATM module to resolve a destination
168 * IP address to an ATM address in order to open an SVC to that destination.
169 * If a valid mapping is already in our cache, then we just tell the caller
170 * about it and that's that. Otherwise, we have to allocate a new arp entry
171 * and issue a query for the mapping.
172 *
173 * Arguments:
174 * ivp pointer to SVC's IPVCC control block
175 * dst pointer to destination IP address
176 *
177 * Returns:
178 * MAP_VALID - Got the answer, returned via iv_arpent field.
179 * MAP_PROCEEDING - OK so far, querying for peer's mapping
180 * MAP_FAILED - error, unable to allocate resources
181 *
182 */
183int
184uniarp_svcout(ivp, dst)
185 struct ipvcc *ivp;
186 struct in_addr *dst;
187{
188 struct uniip *uip;
189 struct uniarp *uap;
190 int s = splnet();
191
192 ATM_DEBUG2("uniarp_svcout: ivp=%p,dst=0x%x\n", ivp, dst->s_addr);
193
194 ivp->iv_arpent = NULL;
195
196 /*
197 * Get uni interface
198 */
199 uip = (struct uniip *)ivp->iv_ipnif->inf_isintf;
200 if (uip == NULL) {
201 (void) splx(s);
202 return (MAP_FAILED);
203 }
204
205 /*
206 * Lookup IP destination address
207 */
208 UNIARP_LOOKUP(dst->s_addr, uap);
209
210 if (uap) {
211 /*
212 * We've got an entry, verify interface
213 */
214 if (uap->ua_intf != uip) {
215 (void) splx(s);
216 return (MAP_FAILED);
217 }
218
219 /*
220 * Chain this vcc onto entry
221 */
222 LINK2TAIL(ivp, struct ipvcc, uap->ua_ivp, iv_arpnext);
223 ivp->iv_arpent = (struct arpmap *)uap;
224 uap->ua_flags |= UAF_USED;
225
226 if (uap->ua_flags & UAF_VALID) {
227 /*
228 * Entry is valid, we're done
229 */
230 (void) splx(s);
231 return (MAP_VALID);
232 } else {
233 /*
234 * We're already looking for this address
235 */
236 (void) splx(s);
237 return (MAP_PROCEEDING);
238 }
239 }
240
241 /*
242 * No info in the cache. If we're the server, then
243 * we're already authoritative, so just deny request.
244 * If we're a client but the server VCC isn't open we
245 * also deny the request.
246 */
247 if (uip->uip_arpstate != UIAS_CLIENT_ACTIVE) {
248 (void) splx(s);
249 return (MAP_FAILED);
250 }
251
252 /*
253 * We're a client with an open VCC to the server, get a new arp entry
254 */
255 uap = (struct uniarp *)atm_allocate(&uniarp_pool);
256 if (uap == NULL) {
257 (void) splx(s);
258 return (MAP_FAILED);
259 }
260
261 /*
262 * Get entry set up
263 */
264 uap->ua_dstip.s_addr = dst->s_addr;
265 uap->ua_dstatm.address_format = T_ATM_ABSENT;
266 uap->ua_dstatm.address_length = 0;
267 uap->ua_dstatmsub.address_format = T_ATM_ABSENT;
268 uap->ua_dstatmsub.address_length = 0;
269 uap->ua_intf = uip;
270
271 /*
272 * Link ipvcc to arp entry for later notification
273 */
274 LINK2TAIL(ivp, struct ipvcc, uap->ua_ivp, iv_arpnext);
275 ivp->iv_arpent = (struct arpmap *)uap;
276 uap->ua_flags |= UAF_USED;
277
278 /*
279 * Add arp entry to table
280 */
281 UNIARP_ADD(uap);
282
283 /*
284 * Issue arp request for this address
285 */
286 (void) uniarp_arp_req(uip, dst);
287
288 /*
289 * Start retry timer
290 */
291 UNIARP_TIMER(uap, UNIARP_ARP_RETRY);
292
293 (void) splx(s);
294 return (MAP_PROCEEDING);
295}
296
297
298/*
299 * Process a new incoming SVC requiring ATMARP support
300 *
301 * This function is called by the IP/ATM module to resolve a caller's ATM
302 * address to its IP address for an incoming call in order to allow a
303 * bi-directional flow of IP packets on the SVC. If a valid mapping is
304 * already in our cache, then we will use it. Otherwise, we have to allocate
305 * a new arp entry and wait for the SVC to become active so that we can issue
306 * an InATMARP to the peer.
307 *
308 * Arguments:
309 * ivp pointer to SVC's IPVCC control block
310 * dst pointer to caller's ATM address
311 * dstsub pointer to caller's ATM subaddress
312 *
313 * Returns:
314 * MAP_VALID - Got the answer, returned via iv_arpent field.
315 * MAP_PROCEEDING - OK so far, querying for peer's mapping
316 * MAP_FAILED - error, unable to allocate resources
317 *
318 */
319int
320uniarp_svcin(ivp, dst, dstsub)
321 struct ipvcc *ivp;
322 Atm_addr *dst;
323 Atm_addr *dstsub;
324{
325 struct uniip *uip;
326 struct uniarp *uap;
327 int found = 0, i, s = splnet();
328
329 ATM_DEBUG1("uniarp_svcin: ivp=%p\n", ivp);
330
331 /*
332 * Clear ARP entry field
333 */
334 ivp->iv_arpent = NULL;
335
336 /*
337 * Check things out
338 */
339 if ((ivp->iv_flags & IVF_LLC) == 0)
340 return (MAP_FAILED);
341
342 /*
343 * Get uni interface
344 */
345 uip = (struct uniip *)ivp->iv_ipnif->inf_isintf;
346 if (uip == NULL) {
347 (void) splx(s);
348 return (MAP_FAILED);
349 }
350
351 /*
352 * Make sure we're configured as a client or server
353 */
354 if (uip->uip_arpstate == UIAS_NOTCONF) {
355 (void) splx(s);
356 return (MAP_FAILED);
357 }
358
359 /*
360 * If we know the caller's ATM address, look it up
361 */
362 uap = NULL;
363 if (dst->address_format != T_ATM_ABSENT) {
364 for (i = 0; (i < UNIARP_HASHSIZ) && (found == 0); i++) {
365 for (uap = uniarp_arptab[i]; uap; uap = uap->ua_next) {
366 if (ATM_ADDR_EQUAL(dst, &uap->ua_dstatm) &&
367 ATM_ADDR_EQUAL(dstsub, &uap->ua_dstatmsub)){
368 found = 1;
369 break;
370 }
371 }
372 }
373 if (uap == NULL) {
374 for (uap = uniarp_nomaptab; uap; uap = uap->ua_next) {
375 if (ATM_ADDR_EQUAL(dst, &uap->ua_dstatm) &&
376 ATM_ADDR_EQUAL(dstsub, &uap->ua_dstatmsub))
377 break;
378 }
379 }
380 }
381
382 if (uap) {
383 /*
384 * We've got an entry, verify interface
385 */
386 if (uap->ua_intf != uip) {
387 (void) splx(s);
388 return (MAP_FAILED);
389 }
390
391 /*
392 * Chain the vcc onto this entry
393 */
394 LINK2TAIL(ivp, struct ipvcc, uap->ua_ivp, iv_arpnext);
395 ivp->iv_arpent = (struct arpmap *)uap;
396 uap->ua_flags |= UAF_USED;
397
398 if (uap->ua_flags & UAF_VALID) {
399 /*
400 * Entry is valid, we're done
401 */
402 (void) splx(s);
403 return (MAP_VALID);
404 } else {
405 /*
406 * We're already looking for this address
407 */
408 (void) splx(s);
409 return (MAP_PROCEEDING);
410 }
411 }
412
413 /*
414 * No info in the cache - get a new arp entry
415 */
416 uap = (struct uniarp *)atm_allocate(&uniarp_pool);
417 if (uap == NULL) {
418 (void) splx(s);
419 return (MAP_FAILED);
420 }
421
422 /*
423 * Get entry set up
424 */
425 ATM_ADDR_COPY(dst, &uap->ua_dstatm);
426 ATM_ADDR_COPY(dstsub, &uap->ua_dstatmsub);
427 uap->ua_intf = uip;
428
429 /*
430 * Link ipvcc to arp entry for later notification
431 */
432 LINK2TAIL(ivp, struct ipvcc, uap->ua_ivp, iv_arpnext);
433 ivp->iv_arpent = (struct arpmap *)uap;
434 uap->ua_flags |= UAF_USED;
435
436 /*
437 * Add arp entry to 'nomap' table
438 */
439 LINK2TAIL(uap, struct uniarp, uniarp_nomaptab, ua_next);
440
441 (void) splx(s);
442
443 /*
444 * Now we just wait for SVC to become active
445 */
446 return (MAP_PROCEEDING);
447}
448
449
450/*
451 * Process ARP SVC activation notification
452 *
453 * This function is called by the IP/ATM module whenever a previously
454 * opened SVC has successfully been connected.
455 *
456 * Arguments:
457 * ivp pointer to SVC's IPVCC control block
458 *
459 * Returns:
460 * 0 activation processing successful
461 * errno activation failed - reason indicated
462 *
463 */
464int
465uniarp_svcactive(ivp)
466 struct ipvcc *ivp;
467{
468 struct ip_nif *inp;
469 struct uniip *uip;
470 struct uniarp *uap;
471 int err, s = splnet();
472
473 ATM_DEBUG1("uniarp_svcactive: ivp=%p\n", ivp);
474
475 inp = ivp->iv_ipnif;
476 uip = (struct uniip *)inp->inf_isintf;
477 uap = (struct uniarp *)ivp->iv_arpent;
478
479 /*
480 * First, we need to create our CM connection
481 */
482 err = atm_cm_addllc(&uniarp_endpt, ivp, &uniarp_llc,
483 ivp->iv_conn, &ivp->iv_arpconn);
484 if (err) {
485 /*
486 * We don't take no (or maybe) for an answer
487 */
488 if (ivp->iv_arpconn) {
489 (void) atm_cm_release(ivp->iv_arpconn, &uniarp_cause);
490 ivp->iv_arpconn = NULL;
491 }
492 return (err);
493 }
494
495 /*
496 * Is this the client->server vcc??
497 */
498 if (uip->uip_arpsvrvcc == ivp) {
499
500 /*
501 * Yep, go into the client registration phase
502 */
503 uip->uip_arpstate = UIAS_CLIENT_REGISTER;
504
505 /*
506 * To register ourselves, RFC1577 says we should wait
507 * around for the server to send us an InATMARP_Request.
508 * However, draft-1577+ just has us send an ATMARP_Request
509 * for our own address. To keep everyone happy, we'll go
510 * with both and see what works!
511 */
512 (void) uniarp_arp_req(uip, &(IA_SIN(inp->inf_addr)->sin_addr));
513
514 /*
515 * Start retry timer
516 */
517 UNIIP_ARP_TIMER(uip, 1 * ATM_HZ);
518
519 (void) splx(s);
520 return (0);
521 }
522
523 /*
524 * Send an InATMARP_Request on this VCC to find out/notify who's at
525 * the other end. If we're the server, this will start off the
526 * RFC1577 registration procedure. If we're a client, then this
527 * SVC is for user data and it's pretty likely that both ends are
528 * going to be sending packets. So, if we're the caller, we'll be
529 * nice and let the callee know right away who we are. If we're the
530 * callee, let's find out asap the caller's IP address.
531 */
532 (void) uniarp_inarp_req(uip, &uap->ua_dstatm, &uap->ua_dstatmsub, ivp);
533
534 /*
535 * Start retry timer if entry isn't valid yet
536 */
537 if (((uap->ua_flags & UAF_VALID) == 0) &&
538 ((uap->ua_time.ti_flag & TIF_QUEUED) == 0))
539 UNIARP_TIMER(uap, UNIARP_ARP_RETRY);
540
541 (void) splx(s);
542 return (0);
543}
544
545
546/*
547 * Process VCC close
548 *
549 * This function is called just prior to IP/ATM closing a VCC which
550 * supports ATMARP. We'll sever our links to the VCC and then
551 * figure out how much more cleanup we need to do for now.
552 *
553 * Arguments:
554 * ivp pointer to VCC's IPVCC control block
555 *
556 * Returns:
557 * none
558 *
559 */
560void
561uniarp_vcclose(ivp)
562 struct ipvcc *ivp;
563{
564 struct uniip *uip;
565 struct uniarp *uap;
566 int s;
567
568 ATM_DEBUG1("uniarp_vcclose: ivp=%p\n", ivp);
569
570 /*
571 * Close our CM connection
572 */
573 if (ivp->iv_arpconn) {
574 (void) atm_cm_release(ivp->iv_arpconn, &uniarp_cause);
575 ivp->iv_arpconn = NULL;
576 }
577
578 /*
579 * Get atmarp entry
580 */
581 if ((uap = (struct uniarp *)ivp->iv_arpent) == NULL)
582 return;
583 uip = uap->ua_intf;
584
585 s = splnet();
586
587 /*
588 * If this is the arpserver VCC, then schedule ourselves to
589 * reopen the connection soon
590 */
591 if (uip->uip_arpsvrvcc == ivp) {
592 uip->uip_arpsvrvcc = NULL;
593 uip->uip_arpstate = UIAS_CLIENT_POPEN;
594 UNIIP_ARP_CANCEL(uip);
595 UNIIP_ARP_TIMER(uip, 5 * ATM_HZ);
596 }
597
598 /*
599 * Remove IP VCC from chain
600 */
601 UNLINK(ivp, struct ipvcc, uap->ua_ivp, iv_arpnext);
602
603 /*
604 * SVCs and PVCs are handled separately
605 */
606 if (ivp->iv_flags & IVF_SVC) {
607 /*
608 * If the mapping is currently valid or in use, or if there
609 * are other VCCs still using this mapping, we're done for now
610 */
611 if ((uap->ua_flags & (UAF_VALID | UAF_LOCKED)) ||
612 (uap->ua_origin >= UAO_PERM) ||
613 (uap->ua_ivp != NULL)) {
614 (void) splx(s);
615 return;
616 }
617
618 /*
619 * Unlink the entry
620 */
621 if (uap->ua_dstip.s_addr == 0) {
622 UNLINK(uap, struct uniarp, uniarp_nomaptab, ua_next);
623 } else {
624 UNIARP_DELETE(uap);
625 }
626 } else {
627 /*
628 * Remove entry from pvc table
629 */
630 UNLINK(uap, struct uniarp, uniarp_pvctab, ua_next);
631 }
632
633 UNIARP_CANCEL(uap);
634
635 /*
636 * Finally, free the entry
637 */
638 atm_free((caddr_t)uap);
639
640 (void) splx(s);
641 return;
642}
643
644
645/*
646 * Process ATMARP VCC Connected Notification
647 *
648 * Arguments:
649 * toku owner's connection token (ipvcc protocol block)
650 *
651 * Returns:
652 * none
653 *
654 */
655void
656uniarp_connected(toku)
657 void *toku;
658{
659
660 /*
661 * Since we only do atm_cm_addllc()'s on active connections,
662 * we should never get called here...
663 */
664 panic("uniarp_connected");
665}
666
667
668/*
669 * Process ATMARP VCC Cleared Notification
670 *
671 * Arguments:
672 * toku owner's connection token (ipvcc protocol block)
673 * cause pointer to cause code
674 *
675 * Returns:
676 * none
677 *
678 */
679void
680uniarp_cleared(toku, cause)
681 void *toku;
682 struct t_atm_cause *cause;
683{
684 struct ipvcc *ivp = toku;
685 int s;
686
687 s = splnet();
688
689 /*
690 * We're done with VCC
691 */
692 ivp->iv_arpconn = NULL;
693
694 /*
695 * If IP is finished with VCC, then we'll free it
696 */
697 if (ivp->iv_state == IPVCC_FREE)
698 atm_free((caddr_t)ivp);
699
700 (void) splx(s);
701}
702