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