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