Merge from vendor branch FILE:
[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.6 2005/02/12 01:28:07 joerg Exp $
28  */
29
30 /*
31  * IP Over ATM Support
32  * -------------------
33  *
34  * Virtual Channel Manager
35  *
36  */
37
38 #include <netproto/atm/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 (in_broadcast(pvp->ipp_dst.sin_addr, &nip->nif_if) ||
350                     IN_MULTICAST(ntohl(pvp->ipp_dst.sin_addr.s_addr)) ||
351                     ipatm_chknif(pvp->ipp_dst.sin_addr, inp)) {
352                         err = EINVAL;
353                         goto done;
354                 }
355         }
356
357         /*
358          * Allocate IP VCC block
359          */
360         ivp = (struct ipvcc *)atm_allocate(&ipatm_vcpool);
361         if (ivp == NULL) {
362                 err = ENOMEM;
363                 goto done;
364         }
365
366         /*
367          * Initialize the PVC
368          */
369         ivp->iv_flags = IVF_PVC;
370         if (pvp->ipp_encaps == ATM_ENC_LLC)
371                 ivp->iv_flags |= IVF_LLC;
372
373         /*
374          * Fill out connection attributes
375          */
376         if (pvp->ipp_aal == ATM_AAL5) {
377                 if (pvp->ipp_encaps == ATM_ENC_LLC)
378                         ap = &ipatm_aal5llc;
379                 else
380                         ap = &ipatm_aal5null;
381         } else {
382                 ap = &ipatm_aal4null;
383         }
384
385         ap->nif = nip;
386         ap->traffic.v.forward.PCR_all_traffic = nip->nif_pif->pif_pcr;
387         ap->traffic.v.backward.PCR_all_traffic = nip->nif_pif->pif_pcr;
388         ap->called.addr.address_format = T_ATM_PVC_ADDR;
389         ap->called.addr.address_length = sizeof(Atm_addr_pvc);
390         pvcp = (Atm_addr_pvc *)ap->called.addr.address;
391         ATM_PVC_SET_VPI(pvcp, pvp->ipp_vpi);
392         ATM_PVC_SET_VCI(pvcp, pvp->ipp_vci);
393         ap->called.subaddr.address_format = T_ATM_ABSENT;
394         ap->called.subaddr.address_length = 0;
395
396         /*
397          * Create PVC
398          */
399         err = atm_cm_connect(&ipatm_endpt, ivp, ap, &ivp->iv_conn);
400         if (err) {
401                 atm_free((caddr_t)ivp);
402                 goto done;
403         }
404
405         /*
406          * Save PVC information and link in VCC
407          */
408         /* ivp->iv_ = ap->headout; */
409
410         /*
411          * Queue VCC onto its network interface
412          */
413         s = splnet();
414         ipatm_vccnt++;
415         ENQUEUE(ivp, struct ipvcc, iv_elem, inp->inf_vcq);
416         ivp->iv_ipnif = inp;
417         (void) splx(s);
418
419         /*
420          * Set destination IP address and IPVCC state
421          */
422         if (pvp->ipp_dst.sin_addr.s_addr == INADDR_ANY) {
423                 /*
424                  * Initiate ARP processing
425                  */
426                 switch ((*inp->inf_serv->is_arp_pvcopen)(ivp)) {
427
428                 case MAP_PROCEEDING:
429                         /*
430                          * Wait for answer
431                          */
432                         ivp->iv_state = IPVCC_ACTIVE;
433                         break;
434
435                 case MAP_VALID:
436                         /*
437                          * We've got our answer already
438                          */
439                         ivp->iv_state = IPVCC_ACTIVE;
440                         ivp->iv_flags |= IVF_MAPOK;
441                         ivp->iv_dst.s_addr = ivp->iv_arpent->am_dstip.s_addr;
442                         break;
443
444                 case MAP_FAILED:
445                         /*
446                          * Try again later
447                          */
448                         ivp->iv_state = IPVCC_ACTPENT;
449                         IPVCC_TIMER(ivp, 1 * ATM_HZ);
450                         break;
451
452                 default:
453                         panic("ipatm_openpvc: invalid arp_pvcopen return");
454                 }
455
456         } else {
457                 /*
458                  * Use configured IP destination
459                  */
460                 ivp->iv_dst.s_addr = pvp->ipp_dst.sin_addr.s_addr;
461                 ivp->iv_state = IPVCC_ACTIVE;
462                 ivp->iv_flags |= IVF_MAPOK;
463         }
464         *sivp = ivp;
465         return (0);
466
467 done:
468         *sivp = NULL;
469         return (err);
470 }
471
472
473 /*
474  * Create an IP SVC
475  * 
476  * This function will initiate the creation of an IP SVC.  The IP VCC
477  * control block will be initialized and, if required, we will initiate
478  * ARP processing in order to resolve the destination's ATM address.  Once
479  * the destination ATM address is known, ipatm_opensvc() will be called.
480  *
481  * Arguments:
482  *      ifp     pointer to destination ifnet structure
483  *      daf     destination address family type
484  *      dst     pointer to destination address
485  *      sivp    address to return pointer to IP SVC control block
486  *
487  * Returns:
488  *      0       SVC creation was successfully initiated
489  *      errno   creation failed - reason indicated
490  *
491  */
492 int
493 ipatm_createsvc(ifp, daf, dst, sivp)
494         struct ifnet            *ifp;
495         u_short                 daf;
496         caddr_t                 dst;
497         struct ipvcc            **sivp;
498 {
499         struct atm_nif  *nip = (struct atm_nif *)ifp;
500         struct ip_nif   *inp;
501         struct ipvcc    *ivp;
502         struct in_addr  *ip;
503         Atm_addr        *atm;
504         int     s, err = 0;
505
506         /*
507          * Get IP interface and make sure its ready
508          */
509         for (inp = ipatm_nif_head; inp; inp = inp->inf_next) {
510                 if (inp->inf_nif == nip)
511                         break;
512         }
513         if (inp == NULL) {
514                 err = ENXIO;
515                 goto done;
516         }
517         if (inp->inf_state != IPNIF_ACTIVE) {
518                 err = ENETDOWN;
519                 goto done;
520         }
521
522         /*
523          * Validate destination address
524          */
525         if (daf == AF_INET) {
526                 /*
527                  * Destination is IP address
528                  */
529                 ip = (struct in_addr *)dst;
530                 atm = NULL;
531                 if (ip->s_addr == INADDR_ANY) {
532                         err = EADDRNOTAVAIL;
533                         goto done;
534                 }
535         } else if (daf == AF_ATM) {
536                 /*
537                  * Destination is ATM address
538                  */
539                 atm = (Atm_addr *)dst;
540                 ip = NULL;
541                 if (atm->address_format == T_ATM_ABSENT) {
542                         err = EINVAL;
543                         goto done;
544                 }
545         } else {
546                 err = EINVAL;
547                 goto done;
548         }
549
550         /*
551          * Make sure we have services provider and ARP support
552          */
553         if ((inp->inf_serv == NULL) ||
554             (inp->inf_serv->is_arp_svcout == NULL)) {
555                 err = ENETDOWN;
556                 goto done;
557         }
558
559         /*
560          * Allocate IP VCC
561          */
562         ivp = (struct ipvcc *)atm_allocate(&ipatm_vcpool);
563         if (ivp == NULL) {
564                 err = ENOMEM;
565                 goto done;
566         }
567
568         /*
569          * Initialize SVC
570          */
571         ivp->iv_flags = IVF_SVC;
572         ivp->iv_ipnif = inp;
573
574         /*
575          * Get destination ATM address
576          */
577         if (daf == AF_INET) {
578                 /*
579                  * ARP is the way...
580                  */
581                 ivp->iv_dst.s_addr = ip->s_addr;
582
583                 switch ((*inp->inf_serv->is_arp_svcout)(ivp, ip)) {
584
585                 case MAP_PROCEEDING:
586                         /*
587                          * Wait for answer
588                          */
589                         ivp->iv_state = IPVCC_PMAP;
590                         IPVCC_TIMER(ivp, IPATM_ARP_TIME);
591                         break;
592
593                 case MAP_VALID:
594                         /*
595                          * We've got our answer already, so open SVC
596                          */
597                         ivp->iv_flags |= IVF_MAPOK;
598                         err = ipatm_opensvc(ivp);
599                         if (err) {
600                                 (*inp->inf_serv->is_arp_close)(ivp);
601                                 atm_free((caddr_t)ivp);
602                                 goto done;
603                         }
604                         break;
605
606                 case MAP_FAILED:
607                         /*
608                          * So sorry...come again
609                          */
610                         atm_free((caddr_t)ivp);
611                         err = ENETDOWN;
612                         goto done;
613
614                 default:
615                         panic("ipatm_createsvc: invalid arp_svcout return");
616                 }
617         } else {
618                 /*
619                  * We were given the ATM address, so open the SVC
620                  *
621                  * Create temporary arp map entry so that opensvc() works.
622                  * Caller must set up a permanent entry immediately! (yuk)
623                  */
624                 struct arpmap   map;
625
626                 ATM_ADDR_COPY(atm, &map.am_dstatm);
627                 map.am_dstatmsub.address_format = T_ATM_ABSENT;
628                 map.am_dstatmsub.address_length = 0;
629                 ivp->iv_arpent = &map;
630                 err = ipatm_opensvc(ivp);
631                 if (err) {
632                         atm_free((caddr_t)ivp);
633                         goto done;
634                 }
635                 ivp->iv_arpent = NULL;
636         }
637
638         /*
639          * Queue VCC onto its network interface
640          */
641         s = splnet();
642         ipatm_vccnt++;
643         ENQUEUE(ivp, struct ipvcc, iv_elem, inp->inf_vcq);
644         (void) splx(s);
645         *sivp = ivp;
646         return (0);
647
648 done:
649         *sivp = NULL;
650         return (err);
651 }
652
653
654 /*
655  * Open an IP SVC
656  * 
657  * This function will continue the IP SVC creation process.  Here, we
658  * will issue an SVC open to the signalling manager and then wait for
659  * the final SVC setup results.
660  *
661  * Arguments:
662  *      ivp     pointer to IP SVC to open
663  *
664  * Returns:
665  *      0       SVC open was successfully initiated
666  *      errno   open failed - reason indicated
667  *
668  */
669 int
670 ipatm_opensvc(ivp)
671         struct ipvcc    *ivp;
672 {
673         struct ip_nif   *inp = ivp->iv_ipnif;
674         Atm_attributes  *ap;
675         int     err = 0, i;
676
677         /*
678          * Cancel possible arp timeout
679          */
680         IPVCC_CANCEL(ivp);
681
682         /*
683          * Fill out connection attributes
684          */
685         i = ivp->iv_parmx;
686         if (inp->inf_serv->is_vccparm[i].ivc_aal == ATM_AAL5) {
687                 if (inp->inf_serv->is_vccparm[i].ivc_encaps == ATM_ENC_LLC) {
688                         ap = &ipatm_aal5llc;
689                         ivp->iv_flags |= IVF_LLC;
690                 } else {
691                         ap = &ipatm_aal5null;
692                         ivp->iv_flags &= ~IVF_LLC;
693                 }
694         } else {
695                 ap = &ipatm_aal4null;
696                 ivp->iv_flags &= ~IVF_LLC;
697         }
698
699         ap->nif = inp->inf_nif;
700         ap->traffic.v.forward.PCR_all_traffic = inp->inf_nif->nif_pif->pif_pcr;
701         ap->traffic.v.backward.PCR_all_traffic = inp->inf_nif->nif_pif->pif_pcr;
702
703         ATM_ADDR_COPY(&ivp->iv_arpent->am_dstatm, &ap->called.addr);
704         ATM_ADDR_COPY(&ivp->iv_arpent->am_dstatmsub, &ap->called.subaddr);
705
706         /*
707          * Initiate SVC open
708          */
709         err = atm_cm_connect(&ipatm_endpt, ivp, ap, &ivp->iv_conn);
710         switch (err) {
711
712         case EINPROGRESS:
713                 /*
714                  * Call is progressing
715                  */
716                 /* ivp->iv_ = ap->headout; */
717
718                 /*
719                  * Now we just wait for a CALL_CONNECTED event
720                  */
721                 ivp->iv_state = IPVCC_POPEN;
722                 IPVCC_TIMER(ivp, IPATM_SVC_TIME);
723                 err = 0;
724                 break;
725
726         case 0:
727                 /*
728                  * We've been hooked up with a shared VCC
729                  */
730                 /* ivp->iv_ = ap->headout; */
731                 ipatm_activate(ivp);
732                 break;
733         }
734
735         return (err);
736 }
737
738
739 /*
740  * Retry an IP SVC Open
741  * 
742  * This function will attempt to retry a failed SVC open request.  The IP
743  * interface service provider specifies a list of possible VCC parameters
744  * for IP to use.  We will try each set of parameters in turn until either
745  * an open succeeds or we reach the end of the list.
746  * 
747  * Arguments:
748  *      ivp     pointer to IP SVC
749  *
750  * Returns:
751  *      0       SVC (re)open was successfully initiated
752  *      else    retry failed
753  *
754  */
755 int
756 ipatm_retrysvc(ivp)
757         struct ipvcc    *ivp;
758 {
759         struct ip_nif   *inp = ivp->iv_ipnif;
760
761         /*
762          * If there isn't another set of vcc parameters to try, return
763          */
764         if ((++ivp->iv_parmx >= IPATM_VCCPARMS) ||
765             (inp->inf_serv->is_vccparm[ivp->iv_parmx].ivc_aal == 0))
766                 return (1);
767
768         /*
769          * Okay, now initiate open with a new set of parameters
770          */
771         return (ipatm_opensvc(ivp));
772 }
773
774
775 /*
776  * Finish IP SVC Activation
777  * 
778  * Arguments:
779  *      ivp     pointer to IP SVC
780  *
781  * Returns:
782  *      none
783  *
784  */
785 void
786 ipatm_activate(ivp)
787         struct ipvcc    *ivp;
788 {
789
790         /*
791          * Connection is now active
792          */
793         ivp->iv_state = IPVCC_ACTIVE;
794         IPVCC_CANCEL(ivp);
795
796         /*
797          * Tell ARP module that connection is active
798          */
799         if ((*ivp->iv_ipnif->inf_serv->is_arp_svcact)(ivp)) {
800                 (void) ipatm_closevc(ivp, T_ATM_CAUSE_TEMPORARY_FAILURE);
801                 return;
802         }
803
804         /*
805          * Send any queued packet
806          */
807         if ((ivp->iv_flags & IVF_MAPOK) && ivp->iv_queue) {
808                 struct sockaddr_in      sin;
809                 struct ifnet            *ifp;
810
811                 sin.sin_family = AF_INET;
812                 sin.sin_addr.s_addr = ivp->iv_dst.s_addr;
813                 ifp = (struct ifnet *)ivp->iv_ipnif->inf_nif;
814                 (void) ipatm_ifoutput(ifp, ivp->iv_queue, 
815                         (struct sockaddr *)&sin);
816                 ivp->iv_queue = NULL;
817         }
818 }
819
820
821 /*
822  * Process Incoming Calls
823  * 
824  * This function will receive control when an incoming call has been matched
825  * to one of our registered listen parameter blocks.  Assuming the call passes
826  * acceptance criteria and all required resources are available, we will
827  * create an IP SVC and notify the connection manager of our decision.  We
828  * will then await notification of the final SVC setup results.  If any
829  * problems are encountered, we will just tell the connection manager to
830  * reject the call.
831  *
832  * Called at splnet.
833  *
834  * Arguments:
835  *      tok     owner's matched listening token
836  *      cop     pointer to incoming call's connection block
837  *      ap      pointer to incoming call's attributes
838  *      tokp    pointer to location to store our connection token
839  *
840  * Returns:
841  *      0       call is accepted
842  *      errno   call rejected - reason indicated
843  *
844  */
845 int
846 ipatm_incoming(tok, cop, ap, tokp)
847         void            *tok;
848         Atm_connection  *cop;
849         Atm_attributes  *ap;
850         void            **tokp;
851 {
852         struct atm_nif  *nip = ap->nif;
853         struct ip_nif   *inp;
854         struct ipvcc    *ivp = NULL;
855         int     err, cause;
856         int     usellc = 0, mtu = ATM_NIF_MTU;
857
858         /*
859          * Get IP interface and make sure its ready
860          */
861         for (inp = ipatm_nif_head; inp; inp = inp->inf_next) {
862                 if (inp->inf_nif == nip)
863                         break;
864         }
865         if ((inp == NULL) || (inp->inf_state != IPNIF_ACTIVE)) {
866                 err = ENETUNREACH;
867                 cause = T_ATM_CAUSE_SERVICE_OR_OPTION_UNAVAILABLE;
868                 goto reject;
869         }
870
871         /*
872          * Make sure we have services provider and ARP support
873          */
874         if ((inp->inf_serv == NULL) ||
875             (inp->inf_serv->is_arp_svcin == NULL)) {
876                 err = ENETUNREACH;
877                 cause = T_ATM_CAUSE_SERVICE_OR_OPTION_UNAVAILABLE;
878                 goto reject;
879         }
880
881         /*
882          * Check for LLC encapsulation
883          */
884         if ((ap->blli.tag_l2 == T_ATM_PRESENT) &&
885             (ap->blli.v.layer_2_protocol.ID_type == T_ATM_SIMPLE_ID) &&
886             (ap->blli.v.layer_2_protocol.ID.simple_ID == T_ATM_BLLI2_I8802)) {
887                 usellc = 1;
888                 mtu += IPATM_LLC_LEN;
889         }
890
891         /*
892          * Verify requested MTU
893          */
894         if (ap->aal.type == ATM_AAL5) {
895                 if ((ap->aal.v.aal5.forward_max_SDU_size > mtu) ||
896                     (ap->aal.v.aal5.backward_max_SDU_size < mtu)) {
897                         err = ENETUNREACH;
898                         cause = T_ATM_CAUSE_AAL_PARAMETERS_NOT_SUPPORTED;
899                         goto reject;
900                 }
901         } else {
902                 if ((ap->aal.v.aal4.forward_max_SDU_size > mtu) ||
903                     (ap->aal.v.aal4.backward_max_SDU_size < mtu)) {
904                         err = ENETUNREACH;
905                         cause = T_ATM_CAUSE_AAL_PARAMETERS_NOT_SUPPORTED;
906                         goto reject;
907                 }
908         }
909
910         /*
911          * Allocate IP VCC
912          */
913         ivp = (struct ipvcc *)atm_allocate(&ipatm_vcpool);
914         if (ivp == NULL) {
915                 err = ENOMEM;
916                 cause = T_ATM_CAUSE_UNSPECIFIED_RESOURCE_UNAVAILABLE;
917                 goto reject;
918         }
919
920         /*
921          * Initialize SVC
922          */
923         ivp->iv_flags = IVF_SVC;
924         ivp->iv_ipnif = inp;
925         if (usellc)
926                 ivp->iv_flags |= IVF_LLC;
927
928         /*
929          * Lookup ARP entry for destination
930          */
931         switch ((*inp->inf_serv->is_arp_svcin)
932                         (ivp, &ap->calling.addr, &ap->calling.subaddr)) {
933
934         case MAP_PROCEEDING:
935                 /*
936                  * We'll be (hopefully) notified later
937                  */
938                 break;
939
940         case MAP_VALID:
941                 /*
942                  * We've got our answer already
943                  */
944                 ivp->iv_flags |= IVF_MAPOK;
945                 ivp->iv_dst.s_addr = ivp->iv_arpent->am_dstip.s_addr;
946                 break;
947
948         case MAP_FAILED:
949                 /*
950                  * So sorry...come again
951                  */
952                 err = ENETUNREACH;
953                 cause = T_ATM_CAUSE_SERVICE_OR_OPTION_UNAVAILABLE;
954                 goto reject;
955
956         default:
957                 panic("ipatm_incoming: invalid arp_svcin return");
958         }
959
960         /*
961          * Accept SVC connection
962          */
963         ivp->iv_state = IPVCC_PACCEPT;
964
965         /*
966          * Save VCC information
967          */
968         ivp->iv_conn = cop;
969         *tokp = ivp;
970         /* ivp->iv_ = ap->headout; */
971
972         /*
973          * Queue VCC onto its network interface
974          */
975         ipatm_vccnt++;
976         ENQUEUE(ivp, struct ipvcc, iv_elem, inp->inf_vcq);
977
978         /*
979          * Wait for a CALL_CONNECTED event
980          */
981         IPVCC_TIMER(ivp, IPATM_SVC_TIME);
982
983         return (0);
984
985 reject:
986         /*
987          * Clean up after call failure
988          */
989         if (ivp) {
990                 (*inp->inf_serv->is_arp_close)(ivp);
991                 atm_free((caddr_t)ivp);
992         }
993         ap->cause.tag = T_ATM_PRESENT;
994         ap->cause.v = ipatm_cause;
995         ap->cause.v.cause_value = cause;
996         return (err);
997 }
998
999
1000 /*
1001  * Close an IP VCC
1002  * 
1003  * This function will close an IP VCC (PVC or SVC), including notifying 
1004  * the signalling and ARP subsystems of the VCC's demise and cleaning 
1005  * up memory after ourselves.
1006  *
1007  * Arguments:
1008  *      ivp     pointer to VCC
1009  *      code    cause code
1010  *
1011  * Returns:
1012  *      0       VCC successfully closed
1013  *      errno   close failed - reason indicated
1014  *
1015  */
1016 int
1017 ipatm_closevc(ivp, code)
1018         struct ipvcc    *ivp;
1019         int             code;
1020 {
1021         struct ip_nif   *inp = ivp->iv_ipnif;
1022         int     s, err;
1023
1024         /*
1025          * Make sure VCC hasn't been through here already
1026          */
1027         switch (ivp->iv_state) {
1028
1029         case IPVCC_FREE:
1030                 return (EALREADY);
1031         }
1032
1033         /*
1034          * Reset lookup cache
1035          */
1036         if (last_map_ipvcc == ivp) {
1037                 last_map_ipvcc = NULL;
1038                 last_map_ipdst = 0;
1039         }
1040
1041         /*
1042          * Tell ARP about SVCs and dynamic PVCs
1043          */
1044         if (inp->inf_serv && 
1045             ((ivp->iv_flags & IVF_SVC) || inp->inf_serv->is_arp_pvcopen)) {
1046                 (*inp->inf_serv->is_arp_close)(ivp);
1047         }
1048
1049         /*
1050          * Free queued packets
1051          */
1052         if (ivp->iv_queue)
1053                 KB_FREEALL(ivp->iv_queue);
1054
1055         /*
1056          * Cancel any timers
1057          */
1058         IPVCC_CANCEL(ivp);
1059
1060         /*
1061          * Close VCC
1062          */
1063         switch (ivp->iv_state) {
1064
1065         case IPVCC_PMAP:
1066                 break;
1067
1068         case IPVCC_POPEN:
1069         case IPVCC_PACCEPT:
1070         case IPVCC_ACTPENT:
1071         case IPVCC_ACTIVE:
1072                 ipatm_cause.cause_value = code;
1073                 err = atm_cm_release(ivp->iv_conn, &ipatm_cause);
1074                 if (err) {
1075                         log(LOG_ERR, 
1076                                 "ipatm_closevc: release fail: err=%d\n", err);
1077                 }
1078                 break;
1079
1080         case IPVCC_CLOSED:
1081                 break;
1082
1083         default:
1084                 log(LOG_ERR, 
1085                         "ipatm_closevc: unknown state: ivp=%p, state=%d\n",
1086                         ivp, ivp->iv_state);
1087         }
1088
1089         /*
1090          * Remove VCC from network i/f
1091          */
1092         s = splnet();
1093         DEQUEUE(ivp, struct ipvcc, iv_elem, inp->inf_vcq);
1094
1095         /*
1096          * Reset state just to be sure
1097          */
1098         ivp->iv_state = IPVCC_FREE;
1099
1100         /*
1101          * If ARP module is done with VCC too, then free it
1102          */
1103         if (ivp->iv_arpconn == NULL)
1104                 atm_free((caddr_t)ivp);
1105         ipatm_vccnt--;
1106         (void) splx(s);
1107
1108         return (0);
1109 }
1110
1111
1112 /*
1113  * Check if IP address is valid on a Network Interface
1114  * 
1115  * Checks whether the supplied IP address is allowed to be assigned to
1116  * the supplied IP network interface.
1117  *
1118  * Arguments:
1119  *      in      IP address
1120  *      inp     pointer to IP network interface
1121  *
1122  * Returns:
1123  *      0 - OK to assign
1124  *      1 - not valid to assign
1125  *
1126  */
1127 int
1128 ipatm_chknif(in, inp)
1129         struct in_addr  in;
1130         struct ip_nif   *inp;
1131 {
1132         struct in_ifaddr        *ia;
1133         u_long  i;
1134
1135         /*
1136          * Make sure there's an interface requested
1137          */
1138         if (inp == NULL)
1139                 return (1);
1140
1141         /*
1142          * Make sure we have an IP address
1143          */
1144         i = ntohl(in.s_addr);
1145         if (i == 0)
1146                 return (1);
1147
1148         /*
1149          * Make sure an interface address is set 
1150          */
1151         ia = inp->inf_addr;
1152         if (ia == NULL)
1153                 return (1);
1154
1155         /*
1156          * Make sure we're on the right subnet
1157          */
1158         if ((i & ia->ia_subnetmask) != ia->ia_subnet)
1159                 return (1);
1160
1161         return (0);
1162 }
1163
1164
1165 /*
1166  * Map an IP Address to an IP VCC
1167  * 
1168  * Given a destination IP address, this function will return a pointer
1169  * to the appropriate output IP VCC to which to send the packet.
1170  * This is currently implemented using a one-behind cache containing the 
1171  * last successful mapping result.  If the cache lookup fails, then a
1172  * simple linear search of all IP VCCs on the destination network interface 
1173  * is performed.  This is obviously an area to look at for performance 
1174  * improvements.
1175  *
1176  * Arguments:
1177  *      dst     pointer to destination IP address
1178  *      nip     pointer to destination network interface
1179  *
1180  * Returns:
1181  *      addr    pointer to located IP VCC
1182  *      0       no such mapping exists
1183  *
1184  */
1185 struct ipvcc *
1186 ipatm_iptovc(dst, nip)
1187         struct sockaddr_in      *dst;
1188         struct atm_nif          *nip;
1189 {
1190         struct ip_nif   *inp;
1191         struct ipvcc    *ivp;
1192         u_long          dstip = dst->sin_addr.s_addr;
1193         int     s;
1194
1195         /*
1196          * Look in cache first
1197          */
1198         if (last_map_ipdst == dstip)
1199                 return (last_map_ipvcc);
1200
1201         /*
1202          * Oh well, we've got to search for it...first find the interface
1203          */
1204         s = splnet();
1205         for (inp = ipatm_nif_head; inp; inp = inp->inf_next) {
1206                 if (inp->inf_nif == nip)
1207                         break;
1208         }
1209         if (inp == NULL) {
1210                 (void) splx(s);
1211                 return (NULL);
1212         }
1213
1214         /*
1215          * Now home in on the VCC
1216          */
1217         for (ivp = Q_HEAD(inp->inf_vcq, struct ipvcc); ivp;
1218                                 ivp = Q_NEXT(ivp, struct ipvcc, iv_elem)) {
1219                 if (ivp->iv_dst.s_addr == dstip)
1220                         break;
1221         }
1222
1223         /*
1224          * Update lookup cache
1225          */
1226         if (ivp) {
1227                 last_map_ipdst = dstip;
1228                 last_map_ipvcc = ivp;
1229         }
1230         (void) splx(s);
1231
1232         return (ivp);
1233 }
1234