964195428730af6123b0743a593d2f8526639209
[dragonfly.git] / sys / netproto / atm / ipatm / ipatm_vcm.c
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/ipatm/ipatm_vcm.c,v 1.4 1999/08/28 00:48:45 peter Exp $
27  *      @(#) $DragonFly: src/sys/netproto/atm/ipatm/ipatm_vcm.c,v 1.3 2003/08/07 21:17:34 dillon Exp $
28  */
29
30 /*
31  * IP Over ATM Support
32  * -------------------
33  *
34  * Virtual Channel Manager
35  *
36  */
37
38 #include <netatm/kern_include.h>
39
40 #include "ipatm.h"
41 #include "ipatm_var.h"
42 #include "ipatm_serv.h"
43
44 Atm_attributes  ipatm_aal5llc = {
45         NULL,                   /* nif */
46         CMAPI_CPCS,             /* api */
47         0,                      /* api_init */
48         0,                      /* headin */
49         0,                      /* headout */
50         {                       /* aal */
51                 T_ATM_PRESENT,
52                 ATM_AAL5
53         },
54         {                       /* traffic */
55                 T_ATM_PRESENT,
56                 {
57                         {
58                                 T_ATM_ABSENT,
59                                 0,
60                                 T_ATM_ABSENT,
61                                 T_ATM_ABSENT,
62                                 T_ATM_ABSENT,
63                                 T_ATM_ABSENT,
64                                 T_NO
65                         },
66                         {
67                                 T_ATM_ABSENT,
68                                 0,
69                                 T_ATM_ABSENT,
70                                 T_ATM_ABSENT,
71                                 T_ATM_ABSENT,
72                                 T_ATM_ABSENT,
73                                 T_NO
74                         },
75                         T_YES
76                 },
77         },
78         {                       /* bearer */
79                 T_ATM_PRESENT,
80                 {
81                         T_ATM_CLASS_X,
82                         T_ATM_NULL,
83                         T_ATM_NULL,
84                         T_NO,
85                         T_ATM_1_TO_1
86                 }
87         },
88         {                       /* bhli */
89                 T_ATM_ABSENT
90         },
91         {                       /* blli */
92                 T_ATM_PRESENT,
93                 T_ATM_ABSENT,
94                 {
95                         {
96                                 T_ATM_SIMPLE_ID,
97                         },
98                         {
99                                 T_ATM_ABSENT
100                         }
101                 }
102         },
103         {                       /* llc */
104                 T_ATM_PRESENT,
105                 {
106                         T_ATM_LLC_SHARING,
107                         IPATM_LLC_LEN,
108                         IPATM_LLC_HDR
109                 }
110         },
111         {                       /* called */
112                 T_ATM_PRESENT,
113         },
114         {                       /* calling */
115                 T_ATM_ABSENT
116         },
117         {                       /* qos */
118                 T_ATM_PRESENT,
119                 {
120                         T_ATM_NETWORK_CODING,
121                         {
122                                 T_ATM_QOS_CLASS_0,
123                         },
124                         {
125                                 T_ATM_QOS_CLASS_0
126                         }
127                 }
128         },
129         {                       /* transit */
130                 T_ATM_ABSENT
131         },
132         {                       /* cause */
133                 T_ATM_ABSENT
134         }
135 };
136
137 Atm_attributes  ipatm_aal5null = {
138         NULL,                   /* nif */
139         CMAPI_CPCS,             /* api */
140         0,                      /* api_init */
141         sizeof(struct ifnet *), /* headin */
142         0,                      /* headout */
143         {                       /* aal */
144                 T_ATM_PRESENT,
145                 ATM_AAL5
146         },
147         {                       /* traffic */
148                 T_ATM_PRESENT,
149                 {
150                         {
151                                 T_ATM_ABSENT,
152                                 0,
153                                 T_ATM_ABSENT,
154                                 T_ATM_ABSENT,
155                                 T_ATM_ABSENT,
156                                 T_ATM_ABSENT,
157                                 T_NO
158                         },
159                         {
160                                 T_ATM_ABSENT,
161                                 0,
162                                 T_ATM_ABSENT,
163                                 T_ATM_ABSENT,
164                                 T_ATM_ABSENT,
165                                 T_ATM_ABSENT,
166                                 T_NO
167                         },
168                         T_YES
169                 },
170         },
171         {                       /* bearer */
172                 T_ATM_PRESENT,
173                 {
174                         T_ATM_CLASS_X,
175                         T_ATM_NULL,
176                         T_ATM_NULL,
177                         T_NO,
178                         T_ATM_1_TO_1
179                 }
180         },
181         {                       /* bhli */
182                 T_ATM_ABSENT
183         },
184         {                       /* blli */
185                 T_ATM_ABSENT,
186                 T_ATM_ABSENT
187         },
188         {                       /* llc */
189                 T_ATM_ABSENT
190         },
191         {                       /* called */
192                 T_ATM_PRESENT,
193         },
194         {                       /* calling */
195                 T_ATM_ABSENT
196         },
197         {                       /* qos */
198                 T_ATM_PRESENT,
199                 {
200                         T_ATM_NETWORK_CODING,
201                         {
202                                 T_ATM_QOS_CLASS_0,
203                         },
204                         {
205                                 T_ATM_QOS_CLASS_0
206                         }
207                 }
208         },
209         {                       /* transit */
210                 T_ATM_ABSENT
211         },
212         {                       /* cause */
213                 T_ATM_ABSENT
214         }
215 };
216
217 Atm_attributes  ipatm_aal4null = {
218         NULL,                   /* nif */
219         CMAPI_CPCS,             /* api */
220         0,                      /* api_init */
221         sizeof(struct ifnet *), /* headin */
222         0,                      /* headout */
223         {                       /* aal */
224                 T_ATM_PRESENT,
225                 ATM_AAL3_4
226         },
227         {                       /* traffic */
228                 T_ATM_PRESENT,
229                 {
230                         {
231                                 T_ATM_ABSENT,
232                                 0,
233                                 T_ATM_ABSENT,
234                                 T_ATM_ABSENT,
235                                 T_ATM_ABSENT,
236                                 T_ATM_ABSENT,
237                                 T_NO
238                         },
239                         {
240                                 T_ATM_ABSENT,
241                                 0,
242                                 T_ATM_ABSENT,
243                                 T_ATM_ABSENT,
244                                 T_ATM_ABSENT,
245                                 T_ATM_ABSENT,
246                                 T_NO
247                         },
248                         T_YES
249                 },
250         },
251         {                       /* bearer */
252                 T_ATM_PRESENT,
253                 {
254                         T_ATM_CLASS_X,
255                         T_ATM_NULL,
256                         T_ATM_NULL,
257                         T_NO,
258                         T_ATM_1_TO_1
259                 }
260         },
261         {                       /* bhli */
262                 T_ATM_ABSENT
263         },
264         {                       /* blli */
265                 T_ATM_ABSENT,
266                 T_ATM_ABSENT
267         },
268         {                       /* llc */
269                 T_ATM_ABSENT
270         },
271         {                       /* called */
272                 T_ATM_PRESENT,
273         },
274         {                       /* calling */
275                 T_ATM_ABSENT
276         },
277         {                       /* qos */
278                 T_ATM_PRESENT,
279                 {
280                         T_ATM_NETWORK_CODING,
281                         {
282                                 T_ATM_QOS_CLASS_0,
283                         },
284                         {
285                                 T_ATM_QOS_CLASS_0
286                         }
287                 }
288         },
289         {                       /* transit */
290                 T_ATM_ABSENT
291         },
292         {                       /* cause */
293                 T_ATM_ABSENT
294         }
295 };
296
297 static struct t_atm_cause       ipatm_cause = {
298         T_ATM_ITU_CODING,
299         T_ATM_LOC_USER,
300         0,
301         {0, 0, 0, 0}
302 };
303
304
305 /*
306  * Open an IP PVC
307  * 
308  * This function will perform all actions necessary to activate a
309  * PVC for IP usage.  In particular, it will allocate control blocks, 
310  * open the PVC, initialize PVC stack, and initiate whatever ARP
311  * procedures are required.
312  *
313  * Arguments:
314  *      pvp     pointer to PVC parameter structure
315  *      sivp    address to return pointer to IP PVC control block
316  *
317  * Returns:
318  *      0       PVC was successfully opened
319  *      errno   open failed - reason indicated
320  *
321  */
322 int
323 ipatm_openpvc(pvp, sivp)
324         struct ipatmpvc *pvp;
325         struct ipvcc    **sivp;
326 {
327         struct ipvcc    *ivp;
328         Atm_attributes  *ap;
329         Atm_addr_pvc    *pvcp;
330         struct atm_nif  *nip;
331         struct ip_nif   *inp;
332         int     s, err = 0;
333
334         inp = pvp->ipp_ipnif;
335         nip = inp->inf_nif;
336
337         /*
338          * Make sure interface is ready to go
339          */
340         if (inp->inf_state != IPNIF_ACTIVE) {
341                 err = ENETDOWN;
342                 goto done;
343         }
344
345         /*
346          * Validate fixed destination IP address
347          */
348         if (pvp->ipp_dst.sin_addr.s_addr != INADDR_ANY) {
349 #if (defined(BSD) && (BSD >= 199306))
350                 if (in_broadcast(pvp->ipp_dst.sin_addr, &nip->nif_if) ||
351 #else
352                 if (in_broadcast(pvp->ipp_dst.sin_addr) ||
353 #endif
354                     IN_MULTICAST(ntohl(pvp->ipp_dst.sin_addr.s_addr)) ||
355                     ipatm_chknif(pvp->ipp_dst.sin_addr, inp)) {
356                         err = EINVAL;
357                         goto done;
358                 }
359         }
360
361         /*
362          * Allocate IP VCC block
363          */
364         ivp = (struct ipvcc *)atm_allocate(&ipatm_vcpool);
365         if (ivp == NULL) {
366                 err = ENOMEM;
367                 goto done;
368         }
369
370         /*
371          * Initialize the PVC
372          */
373         ivp->iv_flags = IVF_PVC;
374         if (pvp->ipp_encaps == ATM_ENC_LLC)
375                 ivp->iv_flags |= IVF_LLC;
376
377         /*
378          * Fill out connection attributes
379          */
380         if (pvp->ipp_aal == ATM_AAL5) {
381                 if (pvp->ipp_encaps == ATM_ENC_LLC)
382                         ap = &ipatm_aal5llc;
383                 else
384                         ap = &ipatm_aal5null;
385         } else {
386                 ap = &ipatm_aal4null;
387         }
388
389         ap->nif = nip;
390         ap->traffic.v.forward.PCR_all_traffic = nip->nif_pif->pif_pcr;
391         ap->traffic.v.backward.PCR_all_traffic = nip->nif_pif->pif_pcr;
392         ap->called.addr.address_format = T_ATM_PVC_ADDR;
393         ap->called.addr.address_length = sizeof(Atm_addr_pvc);
394         pvcp = (Atm_addr_pvc *)ap->called.addr.address;
395         ATM_PVC_SET_VPI(pvcp, pvp->ipp_vpi);
396         ATM_PVC_SET_VCI(pvcp, pvp->ipp_vci);
397         ap->called.subaddr.address_format = T_ATM_ABSENT;
398         ap->called.subaddr.address_length = 0;
399
400         /*
401          * Create PVC
402          */
403         err = atm_cm_connect(&ipatm_endpt, ivp, ap, &ivp->iv_conn);
404         if (err) {
405                 atm_free((caddr_t)ivp);
406                 goto done;
407         }
408
409         /*
410          * Save PVC information and link in VCC
411          */
412         /* ivp->iv_ = ap->headout; */
413
414         /*
415          * Queue VCC onto its network interface
416          */
417         s = splnet();
418         ipatm_vccnt++;
419         ENQUEUE(ivp, struct ipvcc, iv_elem, inp->inf_vcq);
420         ivp->iv_ipnif = inp;
421         (void) splx(s);
422
423         /*
424          * Set destination IP address and IPVCC state
425          */
426         if (pvp->ipp_dst.sin_addr.s_addr == INADDR_ANY) {
427                 /*
428                  * Initiate ARP processing
429                  */
430                 switch ((*inp->inf_serv->is_arp_pvcopen)(ivp)) {
431
432                 case MAP_PROCEEDING:
433                         /*
434                          * Wait for answer
435                          */
436                         ivp->iv_state = IPVCC_ACTIVE;
437                         break;
438
439                 case MAP_VALID:
440                         /*
441                          * We've got our answer already
442                          */
443                         ivp->iv_state = IPVCC_ACTIVE;
444                         ivp->iv_flags |= IVF_MAPOK;
445                         ivp->iv_dst.s_addr = ivp->iv_arpent->am_dstip.s_addr;
446                         break;
447
448                 case MAP_FAILED:
449                         /*
450                          * Try again later
451                          */
452                         ivp->iv_state = IPVCC_ACTPENT;
453                         IPVCC_TIMER(ivp, 1 * ATM_HZ);
454                         break;
455
456                 default:
457                         panic("ipatm_openpvc: invalid arp_pvcopen return");
458                 }
459
460         } else {
461                 /*
462                  * Use configured IP destination
463                  */
464                 ivp->iv_dst.s_addr = pvp->ipp_dst.sin_addr.s_addr;
465                 ivp->iv_state = IPVCC_ACTIVE;
466                 ivp->iv_flags |= IVF_MAPOK;
467         }
468
469 done:
470         if (err)
471                 *sivp = NULL;
472         else
473                 *sivp = ivp;
474         return (err);
475 }
476
477
478 /*
479  * Create an IP SVC
480  * 
481  * This function will initiate the creation of an IP SVC.  The IP VCC
482  * control block will be initialized and, if required, we will initiate
483  * ARP processing in order to resolve the destination's ATM address.  Once
484  * the destination ATM address is known, ipatm_opensvc() will be called.
485  *
486  * Arguments:
487  *      ifp     pointer to destination ifnet structure
488  *      daf     destination address family type
489  *      dst     pointer to destination address
490  *      sivp    address to return pointer to IP SVC control block
491  *
492  * Returns:
493  *      0       SVC creation was successfully initiated
494  *      errno   creation failed - reason indicated
495  *
496  */
497 int
498 ipatm_createsvc(ifp, daf, dst, sivp)
499         struct ifnet            *ifp;
500         u_short                 daf;
501         caddr_t                 dst;
502         struct ipvcc            **sivp;
503 {
504         struct atm_nif  *nip = (struct atm_nif *)ifp;
505         struct ip_nif   *inp;
506         struct ipvcc    *ivp;
507         struct in_addr  *ip;
508         Atm_addr        *atm;
509         int     s, err = 0;
510
511         /*
512          * Get IP interface and make sure its ready
513          */
514         for (inp = ipatm_nif_head; inp; inp = inp->inf_next) {
515                 if (inp->inf_nif == nip)
516                         break;
517         }
518         if (inp == NULL) {
519                 err = ENXIO;
520                 goto done;
521         }
522         if (inp->inf_state != IPNIF_ACTIVE) {
523                 err = ENETDOWN;
524                 goto done;
525         }
526
527         /*
528          * Validate destination address
529          */
530         if (daf == AF_INET) {
531                 /*
532                  * Destination is IP address
533                  */
534                 ip = (struct in_addr *)dst;
535                 atm = NULL;
536                 if (ip->s_addr == INADDR_ANY) {
537                         err = EADDRNOTAVAIL;
538                         goto done;
539                 }
540         } else if (daf == AF_ATM) {
541                 /*
542                  * Destination is ATM address
543                  */
544                 atm = (Atm_addr *)dst;
545                 ip = NULL;
546                 if (atm->address_format == T_ATM_ABSENT) {
547                         err = EINVAL;
548                         goto done;
549                 }
550         } else {
551                 err = EINVAL;
552                 goto done;
553         }
554
555         /*
556          * Make sure we have services provider and ARP support
557          */
558         if ((inp->inf_serv == NULL) ||
559             (inp->inf_serv->is_arp_svcout == NULL)) {
560                 err = ENETDOWN;
561                 goto done;
562         }
563
564         /*
565          * Allocate IP VCC
566          */
567         ivp = (struct ipvcc *)atm_allocate(&ipatm_vcpool);
568         if (ivp == NULL) {
569                 err = ENOMEM;
570                 goto done;
571         }
572
573         /*
574          * Initialize SVC
575          */
576         ivp->iv_flags = IVF_SVC;
577         ivp->iv_ipnif = inp;
578
579         /*
580          * Get destination ATM address
581          */
582         if (daf == AF_INET) {
583                 /*
584                  * ARP is the way...
585                  */
586                 ivp->iv_dst.s_addr = ip->s_addr;
587
588                 switch ((*inp->inf_serv->is_arp_svcout)(ivp, ip)) {
589
590                 case MAP_PROCEEDING:
591                         /*
592                          * Wait for answer
593                          */
594                         ivp->iv_state = IPVCC_PMAP;
595                         IPVCC_TIMER(ivp, IPATM_ARP_TIME);
596                         break;
597
598                 case MAP_VALID:
599                         /*
600                          * We've got our answer already, so open SVC
601                          */
602                         ivp->iv_flags |= IVF_MAPOK;
603                         err = ipatm_opensvc(ivp);
604                         if (err) {
605                                 (*inp->inf_serv->is_arp_close)(ivp);
606                                 atm_free((caddr_t)ivp);
607                                 goto done;
608                         }
609                         break;
610
611                 case MAP_FAILED:
612                         /*
613                          * So sorry...come again
614                          */
615                         atm_free((caddr_t)ivp);
616                         err = ENETDOWN;
617                         goto done;
618
619                 default:
620                         panic("ipatm_createsvc: invalid arp_svcout return");
621                 }
622         } else {
623                 /*
624                  * We were given the ATM address, so open the SVC
625                  *
626                  * Create temporary arp map entry so that opensvc() works.
627                  * Caller must set up a permanent entry immediately! (yuk)
628                  */
629                 struct arpmap   map;
630
631                 ATM_ADDR_COPY(atm, &map.am_dstatm);
632                 map.am_dstatmsub.address_format = T_ATM_ABSENT;
633                 map.am_dstatmsub.address_length = 0;
634                 ivp->iv_arpent = &map;
635                 err = ipatm_opensvc(ivp);
636                 if (err) {
637                         atm_free((caddr_t)ivp);
638                         goto done;
639                 }
640                 ivp->iv_arpent = NULL;
641         }
642
643         /*
644          * Queue VCC onto its network interface
645          */
646         s = splnet();
647         ipatm_vccnt++;
648         ENQUEUE(ivp, struct ipvcc, iv_elem, inp->inf_vcq);
649         (void) splx(s);
650
651 done:
652         if (err)
653                 *sivp = NULL;
654         else
655                 *sivp = ivp;
656         return (err);
657 }
658
659
660 /*
661  * Open an IP SVC
662  * 
663  * This function will continue the IP SVC creation process.  Here, we
664  * will issue an SVC open to the signalling manager and then wait for
665  * the final SVC setup results.
666  *
667  * Arguments:
668  *      ivp     pointer to IP SVC to open
669  *
670  * Returns:
671  *      0       SVC open was successfully initiated
672  *      errno   open failed - reason indicated
673  *
674  */
675 int
676 ipatm_opensvc(ivp)
677         struct ipvcc    *ivp;
678 {
679         struct ip_nif   *inp = ivp->iv_ipnif;
680         Atm_attributes  *ap;
681         int     err = 0, i;
682
683         /*
684          * Cancel possible arp timeout
685          */
686         IPVCC_CANCEL(ivp);
687
688         /*
689          * Fill out connection attributes
690          */
691         i = ivp->iv_parmx;
692         if (inp->inf_serv->is_vccparm[i].ivc_aal == ATM_AAL5) {
693                 if (inp->inf_serv->is_vccparm[i].ivc_encaps == ATM_ENC_LLC) {
694                         ap = &ipatm_aal5llc;
695                         ivp->iv_flags |= IVF_LLC;
696                 } else {
697                         ap = &ipatm_aal5null;
698                         ivp->iv_flags &= ~IVF_LLC;
699                 }
700         } else {
701                 ap = &ipatm_aal4null;
702                 ivp->iv_flags &= ~IVF_LLC;
703         }
704
705         ap->nif = inp->inf_nif;
706         ap->traffic.v.forward.PCR_all_traffic = inp->inf_nif->nif_pif->pif_pcr;
707         ap->traffic.v.backward.PCR_all_traffic = inp->inf_nif->nif_pif->pif_pcr;
708
709         ATM_ADDR_COPY(&ivp->iv_arpent->am_dstatm, &ap->called.addr);
710         ATM_ADDR_COPY(&ivp->iv_arpent->am_dstatmsub, &ap->called.subaddr);
711
712         /*
713          * Initiate SVC open
714          */
715         err = atm_cm_connect(&ipatm_endpt, ivp, ap, &ivp->iv_conn);
716         switch (err) {
717
718         case EINPROGRESS:
719                 /*
720                  * Call is progressing
721                  */
722                 /* ivp->iv_ = ap->headout; */
723
724                 /*
725                  * Now we just wait for a CALL_CONNECTED event
726                  */
727                 ivp->iv_state = IPVCC_POPEN;
728                 IPVCC_TIMER(ivp, IPATM_SVC_TIME);
729                 err = 0;
730                 break;
731
732         case 0:
733                 /*
734                  * We've been hooked up with a shared VCC
735                  */
736                 /* ivp->iv_ = ap->headout; */
737                 ipatm_activate(ivp);
738                 break;
739         }
740
741         return (err);
742 }
743
744
745 /*
746  * Retry an IP SVC Open
747  * 
748  * This function will attempt to retry a failed SVC open request.  The IP
749  * interface service provider specifies a list of possible VCC parameters
750  * for IP to use.  We will try each set of parameters in turn until either
751  * an open succeeds or we reach the end of the list.
752  * 
753  * Arguments:
754  *      ivp     pointer to IP SVC
755  *
756  * Returns:
757  *      0       SVC (re)open was successfully initiated
758  *      else    retry failed
759  *
760  */
761 int
762 ipatm_retrysvc(ivp)
763         struct ipvcc    *ivp;
764 {
765         struct ip_nif   *inp = ivp->iv_ipnif;
766
767         /*
768          * If there isn't another set of vcc parameters to try, return
769          */
770         if ((++ivp->iv_parmx >= IPATM_VCCPARMS) ||
771             (inp->inf_serv->is_vccparm[ivp->iv_parmx].ivc_aal == 0))
772                 return (1);
773
774         /*
775          * Okay, now initiate open with a new set of parameters
776          */
777         return (ipatm_opensvc(ivp));
778 }
779
780
781 /*
782  * Finish IP SVC Activation
783  * 
784  * Arguments:
785  *      ivp     pointer to IP SVC
786  *
787  * Returns:
788  *      none
789  *
790  */
791 void
792 ipatm_activate(ivp)
793         struct ipvcc    *ivp;
794 {
795
796         /*
797          * Connection is now active
798          */
799         ivp->iv_state = IPVCC_ACTIVE;
800         IPVCC_CANCEL(ivp);
801
802         /*
803          * Tell ARP module that connection is active
804          */
805         if ((*ivp->iv_ipnif->inf_serv->is_arp_svcact)(ivp)) {
806                 (void) ipatm_closevc(ivp, T_ATM_CAUSE_TEMPORARY_FAILURE);
807                 return;
808         }
809
810         /*
811          * Send any queued packet
812          */
813         if ((ivp->iv_flags & IVF_MAPOK) && ivp->iv_queue) {
814                 struct sockaddr_in      sin;
815                 struct ifnet            *ifp;
816
817                 sin.sin_family = AF_INET;
818                 sin.sin_addr.s_addr = ivp->iv_dst.s_addr;
819                 ifp = (struct ifnet *)ivp->iv_ipnif->inf_nif;
820                 (void) ipatm_ifoutput(ifp, ivp->iv_queue, 
821                         (struct sockaddr *)&sin);
822                 ivp->iv_queue = NULL;
823         }
824 }
825
826
827 /*
828  * Process Incoming Calls
829  * 
830  * This function will receive control when an incoming call has been matched
831  * to one of our registered listen parameter blocks.  Assuming the call passes
832  * acceptance criteria and all required resources are available, we will
833  * create an IP SVC and notify the connection manager of our decision.  We
834  * will then await notification of the final SVC setup results.  If any
835  * problems are encountered, we will just tell the connection manager to
836  * reject the call.
837  *
838  * Called at splnet.
839  *
840  * Arguments:
841  *      tok     owner's matched listening token
842  *      cop     pointer to incoming call's connection block
843  *      ap      pointer to incoming call's attributes
844  *      tokp    pointer to location to store our connection token
845  *
846  * Returns:
847  *      0       call is accepted
848  *      errno   call rejected - reason indicated
849  *
850  */
851 int
852 ipatm_incoming(tok, cop, ap, tokp)
853         void            *tok;
854         Atm_connection  *cop;
855         Atm_attributes  *ap;
856         void            **tokp;
857 {
858         struct atm_nif  *nip = ap->nif;
859         struct ip_nif   *inp;
860         struct ipvcc    *ivp = NULL;
861         int     err, cause;
862         int     usellc = 0, mtu = ATM_NIF_MTU;
863
864         /*
865          * Get IP interface and make sure its ready
866          */
867         for (inp = ipatm_nif_head; inp; inp = inp->inf_next) {
868                 if (inp->inf_nif == nip)
869                         break;
870         }
871         if ((inp == NULL) || (inp->inf_state != IPNIF_ACTIVE)) {
872                 err = ENETUNREACH;
873                 cause = T_ATM_CAUSE_SERVICE_OR_OPTION_UNAVAILABLE;
874                 goto reject;
875         }
876
877         /*
878          * Make sure we have services provider and ARP support
879          */
880         if ((inp->inf_serv == NULL) ||
881             (inp->inf_serv->is_arp_svcin == NULL)) {
882                 err = ENETUNREACH;
883                 cause = T_ATM_CAUSE_SERVICE_OR_OPTION_UNAVAILABLE;
884                 goto reject;
885         }
886
887         /*
888          * Check for LLC encapsulation
889          */
890         if ((ap->blli.tag_l2 == T_ATM_PRESENT) &&
891             (ap->blli.v.layer_2_protocol.ID_type == T_ATM_SIMPLE_ID) &&
892             (ap->blli.v.layer_2_protocol.ID.simple_ID == T_ATM_BLLI2_I8802)) {
893                 usellc = 1;
894                 mtu += IPATM_LLC_LEN;
895         }
896
897         /*
898          * Verify requested MTU
899          */
900         if (ap->aal.type == ATM_AAL5) {
901                 if ((ap->aal.v.aal5.forward_max_SDU_size > mtu) ||
902                     (ap->aal.v.aal5.backward_max_SDU_size < mtu)) {
903                         err = ENETUNREACH;
904                         cause = T_ATM_CAUSE_AAL_PARAMETERS_NOT_SUPPORTED;
905                         goto reject;
906                 }
907         } else {
908                 if ((ap->aal.v.aal4.forward_max_SDU_size > mtu) ||
909                     (ap->aal.v.aal4.backward_max_SDU_size < mtu)) {
910                         err = ENETUNREACH;
911                         cause = T_ATM_CAUSE_AAL_PARAMETERS_NOT_SUPPORTED;
912                         goto reject;
913                 }
914         }
915
916         /*
917          * Allocate IP VCC
918          */
919         ivp = (struct ipvcc *)atm_allocate(&ipatm_vcpool);
920         if (ivp == NULL) {
921                 err = ENOMEM;
922                 cause = T_ATM_CAUSE_UNSPECIFIED_RESOURCE_UNAVAILABLE;
923                 goto reject;
924         }
925
926         /*
927          * Initialize SVC
928          */
929         ivp->iv_flags = IVF_SVC;
930         ivp->iv_ipnif = inp;
931         if (usellc)
932                 ivp->iv_flags |= IVF_LLC;
933
934         /*
935          * Lookup ARP entry for destination
936          */
937         switch ((*inp->inf_serv->is_arp_svcin)
938                         (ivp, &ap->calling.addr, &ap->calling.subaddr)) {
939
940         case MAP_PROCEEDING:
941                 /*
942                  * We'll be (hopefully) notified later
943                  */
944                 break;
945
946         case MAP_VALID:
947                 /*
948                  * We've got our answer already
949                  */
950                 ivp->iv_flags |= IVF_MAPOK;
951                 ivp->iv_dst.s_addr = ivp->iv_arpent->am_dstip.s_addr;
952                 break;
953
954         case MAP_FAILED:
955                 /*
956                  * So sorry...come again
957                  */
958                 err = ENETUNREACH;
959                 cause = T_ATM_CAUSE_SERVICE_OR_OPTION_UNAVAILABLE;
960                 goto reject;
961
962         default:
963                 panic("ipatm_incoming: invalid arp_svcin return");
964         }
965
966         /*
967          * Accept SVC connection
968          */
969         ivp->iv_state = IPVCC_PACCEPT;
970
971         /*
972          * Save VCC information
973          */
974         ivp->iv_conn = cop;
975         *tokp = ivp;
976         /* ivp->iv_ = ap->headout; */
977
978         /*
979          * Queue VCC onto its network interface
980          */
981         ipatm_vccnt++;
982         ENQUEUE(ivp, struct ipvcc, iv_elem, inp->inf_vcq);
983
984         /*
985          * Wait for a CALL_CONNECTED event
986          */
987         IPVCC_TIMER(ivp, IPATM_SVC_TIME);
988
989         return (0);
990
991 reject:
992         /*
993          * Clean up after call failure
994          */
995         if (ivp) {
996                 (*inp->inf_serv->is_arp_close)(ivp);
997                 atm_free((caddr_t)ivp);
998         }
999         ap->cause.tag = T_ATM_PRESENT;
1000         ap->cause.v = ipatm_cause;
1001         ap->cause.v.cause_value = cause;
1002         return (err);
1003 }
1004
1005
1006 /*
1007  * Close an IP VCC
1008  * 
1009  * This function will close an IP VCC (PVC or SVC), including notifying 
1010  * the signalling and ARP subsystems of the VCC's demise and cleaning 
1011  * up memory after ourselves.
1012  *
1013  * Arguments:
1014  *      ivp     pointer to VCC
1015  *      code    cause code
1016  *
1017  * Returns:
1018  *      0       VCC successfully closed
1019  *      errno   close failed - reason indicated
1020  *
1021  */
1022 int
1023 ipatm_closevc(ivp, code)
1024         struct ipvcc    *ivp;
1025         int             code;
1026 {
1027         struct ip_nif   *inp = ivp->iv_ipnif;
1028         int     s, err;
1029
1030         /*
1031          * Make sure VCC hasn't been through here already
1032          */
1033         switch (ivp->iv_state) {
1034
1035         case IPVCC_FREE:
1036                 return (EALREADY);
1037         }
1038
1039         /*
1040          * Reset lookup cache
1041          */
1042         if (last_map_ipvcc == ivp) {
1043                 last_map_ipvcc = NULL;
1044                 last_map_ipdst = 0;
1045         }
1046
1047         /*
1048          * Tell ARP about SVCs and dynamic PVCs
1049          */
1050         if (inp->inf_serv && 
1051             ((ivp->iv_flags & IVF_SVC) || inp->inf_serv->is_arp_pvcopen)) {
1052                 (*inp->inf_serv->is_arp_close)(ivp);
1053         }
1054
1055         /*
1056          * Free queued packets
1057          */
1058         if (ivp->iv_queue)
1059                 KB_FREEALL(ivp->iv_queue);
1060
1061         /*
1062          * Cancel any timers
1063          */
1064         IPVCC_CANCEL(ivp);
1065
1066         /*
1067          * Close VCC
1068          */
1069         switch (ivp->iv_state) {
1070
1071         case IPVCC_PMAP:
1072                 break;
1073
1074         case IPVCC_POPEN:
1075         case IPVCC_PACCEPT:
1076         case IPVCC_ACTPENT:
1077         case IPVCC_ACTIVE:
1078                 ipatm_cause.cause_value = code;
1079                 err = atm_cm_release(ivp->iv_conn, &ipatm_cause);
1080                 if (err) {
1081                         log(LOG_ERR, 
1082                                 "ipatm_closevc: release fail: err=%d\n", err);
1083                 }
1084                 break;
1085
1086         case IPVCC_CLOSED:
1087                 break;
1088
1089         default:
1090                 log(LOG_ERR, 
1091                         "ipatm_closevc: unknown state: ivp=%p, state=%d\n",
1092                         ivp, ivp->iv_state);
1093         }
1094
1095         /*
1096          * Remove VCC from network i/f
1097          */
1098         s = splnet();
1099         DEQUEUE(ivp, struct ipvcc, iv_elem, inp->inf_vcq);
1100
1101         /*
1102          * Reset state just to be sure
1103          */
1104         ivp->iv_state = IPVCC_FREE;
1105
1106         /*
1107          * If ARP module is done with VCC too, then free it
1108          */
1109         if (ivp->iv_arpconn == NULL)
1110                 atm_free((caddr_t)ivp);
1111         ipatm_vccnt--;
1112         (void) splx(s);
1113
1114         return (0);
1115 }
1116
1117
1118 /*
1119  * Check if IP address is valid on a Network Interface
1120  * 
1121  * Checks whether the supplied IP address is allowed to be assigned to
1122  * the supplied IP network interface.
1123  *
1124  * Arguments:
1125  *      in      IP address
1126  *      inp     pointer to IP network interface
1127  *
1128  * Returns:
1129  *      0 - OK to assign
1130  *      1 - not valid to assign
1131  *
1132  */
1133 int
1134 ipatm_chknif(in, inp)
1135         struct in_addr  in;
1136         struct ip_nif   *inp;
1137 {
1138         struct in_ifaddr        *ia;
1139         u_long  i;
1140
1141         /*
1142          * Make sure there's an interface requested
1143          */
1144         if (inp == NULL)
1145                 return (1);
1146
1147         /*
1148          * Make sure we have an IP address
1149          */
1150         i = ntohl(in.s_addr);
1151         if (i == 0)
1152                 return (1);
1153
1154         /*
1155          * Make sure an interface address is set 
1156          */
1157         ia = inp->inf_addr;
1158         if (ia == NULL)
1159                 return (1);
1160
1161         /*
1162          * Make sure we're on the right subnet
1163          */
1164         if ((i & ia->ia_subnetmask) != ia->ia_subnet)
1165                 return (1);
1166
1167         return (0);
1168 }
1169
1170
1171 /*
1172  * Map an IP Address to an IP VCC
1173  * 
1174  * Given a destination IP address, this function will return a pointer
1175  * to the appropriate output IP VCC to which to send the packet.
1176  * This is currently implemented using a one-behind cache containing the 
1177  * last successful mapping result.  If the cache lookup fails, then a
1178  * simple linear search of all IP VCCs on the destination network interface 
1179  * is performed.  This is obviously an area to look at for performance 
1180  * improvements.
1181  *
1182  * Arguments:
1183  *      dst     pointer to destination IP address
1184  *      nip     pointer to destination network interface
1185  *
1186  * Returns:
1187  *      addr    pointer to located IP VCC
1188  *      0       no such mapping exists
1189  *
1190  */
1191 struct ipvcc *
1192 ipatm_iptovc(dst, nip)
1193         struct sockaddr_in      *dst;
1194         struct atm_nif          *nip;
1195 {
1196         struct ip_nif   *inp;
1197         struct ipvcc    *ivp;
1198         u_long          dstip = dst->sin_addr.s_addr;
1199         int     s;
1200
1201         /*
1202          * Look in cache first
1203          */
1204         if (last_map_ipdst == dstip)
1205                 return (last_map_ipvcc);
1206
1207         /*
1208          * Oh well, we've got to search for it...first find the interface
1209          */
1210         s = splnet();
1211         for (inp = ipatm_nif_head; inp; inp = inp->inf_next) {
1212                 if (inp->inf_nif == nip)
1213                         break;
1214         }
1215         if (inp == NULL) {
1216                 (void) splx(s);
1217                 return (NULL);
1218         }
1219
1220         /*
1221          * Now home in on the VCC
1222          */
1223         for (ivp = Q_HEAD(inp->inf_vcq, struct ipvcc); ivp;
1224                                 ivp = Q_NEXT(ivp, struct ipvcc, iv_elem)) {
1225                 if (ivp->iv_dst.s_addr == dstip)
1226                         break;
1227         }
1228
1229         /*
1230          * Update lookup cache
1231          */
1232         if (ivp) {
1233                 last_map_ipdst = dstip;
1234                 last_map_ipvcc = ivp;
1235         }
1236         (void) splx(s);
1237
1238         return (ivp);
1239 }
1240