kernel: Sync ACPICA with Intel's version 20140424.
[dragonfly.git] / sys / netproto / atm / spans / spans_cls.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/spans/spans_cls.c,v 1.6 1999/08/28 00:48:49 peter Exp $
27  */
28
29 /*
30  * SPANS Signalling Manager
31  * ---------------------------
32  *
33  * SPANS Connectionless Datagram Service (CLS) module
34  *
35  */
36
37 #include <netproto/atm/kern_include.h>
38
39 #include <netproto/atm/ipatm/ipatm_var.h>
40 #include <netproto/atm/ipatm/ipatm_serv.h>
41 #include "spans_xdr.h"
42 #include "spans_var.h"
43 #include "spans_cls.h"
44
45 /*
46  * Global variables
47  */
48 int     spanscls_print = 0;
49
50 struct spanscls *spanscls_head = NULL;
51
52 struct spans_addr       spans_bcastaddr = {
53         { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }
54 };
55
56 struct spanscls_hdr     spanscls_hdr = {
57         { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, /* dst */
58         { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, /* src */
59         0x00, 0x00, 0,
60         0xaa, 0xaa, 0x03, { 0x00, 0x00, 0x00 }, 0               /* LLC SNAP */
61 };
62
63
64 /*
65  * Local functions
66  */
67 static int      spanscls_ipact (struct ip_nif *);
68 static int      spanscls_ipdact (struct ip_nif *);
69 static int      spanscls_bcast_output (struct ip_nif *, KBuffer *);
70 static void     spanscls_cpcs_data (void *, KBuffer *);
71 static void     spanscls_connected (void *);
72 static void     spanscls_cleared (void *, struct t_atm_cause *);
73 static caddr_t  spanscls_getname (void *);
74 static void     spanscls_pdu_print (struct spanscls *, KBuffer *,
75                         char *);
76
77 /*
78  * Local variables
79  */
80 static struct sp_info  spanscls_pool = {
81         "spans cls pool",               /* si_name */
82         sizeof(struct spanscls),        /* si_blksiz */
83         2,                              /* si_blkcnt */
84         100                             /* si_maxallow */
85 };
86
87 static struct ip_serv   spanscls_ipserv = {
88         spanscls_ipact,
89         spanscls_ipdact,
90         spansarp_ioctl,
91         NULL,
92         spansarp_svcout,
93         spansarp_svcin,
94         spansarp_svcactive,
95         spansarp_vcclose,
96         spanscls_bcast_output,
97         {
98                 {ATM_AAL5, ATM_ENC_NULL},
99                 {ATM_AAL3_4, ATM_ENC_NULL}
100         }
101 };
102
103 static u_char   spanscls_bridged[] = {
104         0x00, 0x00, 0x00, 0x00,
105         0xaa, 0xaa, 0x03, 0x00, 0x80, 0xc2      /* LLC SNAP */
106 };
107
108 static Atm_endpoint     spanscls_endpt = {
109         NULL,
110         ENDPT_SPANS_CLS,
111         NULL,
112         spanscls_getname,
113         spanscls_connected,
114         spanscls_cleared,
115         NULL,
116         NULL,
117         NULL,
118         NULL,
119         spanscls_cpcs_data,
120         NULL,
121         NULL,
122         NULL,
123         NULL
124 };
125
126 static Atm_attributes   spanscls_attr = {
127         NULL,                   /* nif */
128         CMAPI_CPCS,             /* api */
129         0,                      /* api_init */
130         0,                      /* headin */
131         0,                      /* headout */
132         {                       /* aal */
133                 T_ATM_PRESENT,
134                 ATM_AAL3_4
135         },
136         {                       /* traffic */
137                 T_ATM_PRESENT,
138                 {
139                         {
140                                 T_ATM_ABSENT,
141                                 0,
142                                 T_ATM_ABSENT,
143                                 T_ATM_ABSENT,
144                                 T_ATM_ABSENT,
145                                 T_ATM_ABSENT,
146                                 T_NO
147                         },
148                         {
149                                 T_ATM_ABSENT,
150                                 0,
151                                 T_ATM_ABSENT,
152                                 T_ATM_ABSENT,
153                                 T_ATM_ABSENT,
154                                 T_ATM_ABSENT,
155                                 T_NO
156                         },
157                         T_YES
158                 },
159         },
160         {                       /* bearer */
161                 T_ATM_PRESENT,
162                 {
163                         T_ATM_CLASS_X,
164                         T_ATM_NULL,
165                         T_ATM_NULL,
166                         T_NO,
167                         T_ATM_1_TO_1
168                 }
169         },
170         {                       /* bhli */
171                 T_ATM_ABSENT
172         },
173         {                       /* blli */
174                 T_ATM_ABSENT,
175                 T_ATM_ABSENT
176         },
177         {                       /* llc */
178                 T_ATM_ABSENT
179         },
180         {                       /* called */
181                 T_ATM_PRESENT,
182         },
183         {                       /* calling */
184                 T_ATM_ABSENT
185         },
186         {                       /* qos */
187                 T_ATM_PRESENT,
188                 {
189                         T_ATM_NETWORK_CODING,
190                         {
191                                 T_ATM_QOS_CLASS_0,
192                         },
193                         {
194                                 T_ATM_QOS_CLASS_0
195                         }
196                 }
197         },
198         {                       /* transit */
199                 T_ATM_ABSENT
200         },
201         {                       /* cause */
202                 T_ATM_ABSENT
203         }
204 };
205
206 static struct t_atm_cause       spanscls_cause = {
207         T_ATM_ITU_CODING,
208         T_ATM_LOC_USER,
209         T_ATM_CAUSE_UNSPECIFIED_NORMAL,
210         {0, 0, 0, 0}
211 };
212
213
214 /*
215  * Process module loading
216  * 
217  * Called whenever the spans module is initializing.  
218  *
219  * Arguments:
220  *      none
221  *
222  * Returns:
223  *      0       initialization successful
224  *      errno   initialization failed - reason indicated
225  *
226  */
227 int
228 spanscls_start(void)
229 {
230         int     err;
231
232         /*
233          * Fill in union fields
234          */
235         spanscls_attr.aal.v.aal4.forward_max_SDU_size = ATM_NIF_MTU;
236         spanscls_attr.aal.v.aal4.backward_max_SDU_size = ATM_NIF_MTU;
237         spanscls_attr.aal.v.aal4.SSCS_type = T_ATM_NULL;
238         spanscls_attr.aal.v.aal4.mid_low = 0;
239         spanscls_attr.aal.v.aal4.mid_high = 1023;
240
241         /*
242          * Register our endpoint
243          */
244         err = atm_endpoint_register(&spanscls_endpt);
245
246         return (err);
247 }
248
249
250 /*
251  * Process module unloading notification
252  * 
253  * Called whenever the spans module is about to be unloaded.  All signalling
254  * instances will have been previously detached.  All spanscls resources
255  * must be freed now.
256  *
257  * Arguments:
258  *      none
259  *
260  * Returns:
261  *      none
262  *
263  */
264 void
265 spanscls_stop(void)
266 {
267         crit_enter();
268
269         /*
270          * Tell ARP to stop
271          */
272         spansarp_stop();
273
274         /*
275          * Nothing should be left here...
276          */
277         if (spanscls_head) {
278                 panic("spanscls_stop: bad state");
279         }
280         crit_exit();
281
282         /*
283          * De-register ourselves
284          */
285         atm_endpoint_deregister(&spanscls_endpt);
286
287         /*
288          * Free our storage pools
289          */
290         atm_release_pool(&spanscls_pool);
291 }
292
293
294 /*
295  * Process signalling interface attach
296  * 
297  * This function is called whenever a physical interface has been attached
298  * to spans.  We will open the CLS PVC and await further events.
299  *
300  * Called from a critical section.
301  *
302  * Arguments:
303  *      spp     pointer to spans signalling protocol instance
304  *
305  * Returns:
306  *      0       attach successful
307  *      errno   attach failed - reason indicated
308  *
309  */
310 int
311 spanscls_attach(struct spans *spp)
312 {
313         struct spanscls *clp;
314         Atm_addr_pvc    *pvcp;
315         int     err;
316
317         /*
318          * Get a new cls control block
319          */
320         clp = (struct spanscls *)atm_allocate(&spanscls_pool);
321         if (clp == NULL)
322                 return (ENOMEM);
323
324         /*
325          * Initialize some stuff
326          */
327         clp->cls_state = CLS_CLOSED;
328         clp->cls_spans = spp;
329         spp->sp_ipserv = &spanscls_ipserv;
330
331         /*
332          * Fill out connection attributes
333          */
334         spanscls_attr.nif = spp->sp_pif->pif_nif;
335         spanscls_attr.traffic.v.forward.PCR_all_traffic = spp->sp_pif->pif_pcr;
336         spanscls_attr.traffic.v.backward.PCR_all_traffic = spp->sp_pif->pif_pcr;
337         spanscls_attr.called.addr.address_format = T_ATM_PVC_ADDR;
338         spanscls_attr.called.addr.address_length = sizeof(Atm_addr_pvc);
339         pvcp = (Atm_addr_pvc *)spanscls_attr.called.addr.address;
340         ATM_PVC_SET_VPI(pvcp, SPANS_CLS_VPI);
341         ATM_PVC_SET_VCI(pvcp, SPANS_CLS_VCI);
342         spanscls_attr.called.subaddr.address_format = T_ATM_ABSENT;
343         spanscls_attr.called.subaddr.address_length = 0;
344
345         /*
346          * Create SPANS Connectionless Service (CLS) PVC
347          */
348         err = atm_cm_connect(&spanscls_endpt, clp, &spanscls_attr,
349                         &clp->cls_conn);
350         if (err) {
351                 atm_free((caddr_t)clp);
352                 return (err);
353         }
354
355         /*
356          * Set new state and link instance
357          */
358         clp->cls_state = CLS_OPEN;
359         LINK2TAIL(clp, struct spanscls, spanscls_head, cls_next);
360         spp->sp_cls = clp;
361
362         return (0);
363 }
364
365
366 /*
367  * Process signalling interface detach
368  * 
369  * This function is called whenever a physical interface has been detached
370  * from spans.  We will close the CLS PVC and clean up everything.
371  *
372  * Called from a critical section.
373  *
374  * Arguments:
375  *      spp     pointer to spans signalling protocol instance
376  *
377  * Returns:
378  *      none
379  *
380  */
381 void
382 spanscls_detach(struct spans *spp)
383 {
384         struct spanscls *clp;
385
386         /*
387          * Get our control block
388          */
389         clp = spp->sp_cls;
390         if (clp == NULL)
391                 return;
392
393         /*
394          * Just checking up on things...
395          */
396         if (clp->cls_ipnif)
397                 panic("spanscls_detach: IP interface still active");
398
399         /*
400          * Close CLS PVC
401          */
402         spanscls_closevc(clp, &spanscls_cause);
403
404         /*
405          * Sever links and free server block, if possible
406          */
407         clp->cls_spans = NULL;
408         spp->sp_cls = NULL;
409         if (clp->cls_state == CLS_CLOSED) {
410                 UNLINK(clp, struct spanscls, spanscls_head, cls_next);
411                 atm_free((caddr_t)clp);
412         }
413 }
414
415
416 /*
417  * Process IP Network Interface Activation
418  * 
419  * Called whenever an IP network interface becomes active.
420  *
421  * Called from a critical section.
422  *
423  * Arguments:
424  *      inp     pointer to IP network interface
425  *
426  * Returns:
427  *      0       command successful
428  *      errno   command failed - reason indicated
429  *
430  */
431 static int
432 spanscls_ipact(struct ip_nif *inp)
433 {
434         struct spans            *spp;
435         struct spanscls         *clp;
436
437         /*
438          * Get corresponding cls instance
439          */
440         spp = (struct spans *)inp->inf_nif->nif_pif->pif_siginst;
441         if ((spp == NULL) || ((clp = spp->sp_cls) == NULL))
442                 return (ENXIO);
443
444         /*
445          * Make sure it's not already activated
446          */
447         if (clp->cls_ipnif)
448                 return (EEXIST);
449
450         /*
451          * Set two-way links with IP world
452          */
453         clp->cls_ipnif = inp;
454         inp->inf_isintf = (caddr_t)clp;
455
456         /*
457          * Tell arp about new interface
458          */
459         spansarp_ipact(clp);
460
461         return (0);
462 }
463
464
465 /*
466  * Process IP Network Interface Deactivation
467  * 
468  * Called whenever an IP network interface becomes inactive.
469  *
470  * Called from a critical section.
471  *
472  * Arguments:
473  *      inp     pointer to IP network interface
474  *
475  * Returns:
476  *      0       command successful
477  *      errno   command failed - reason indicated
478  *
479  */
480 static int
481 spanscls_ipdact(struct ip_nif *inp)
482 {
483         struct spanscls         *clp;
484
485         /*
486          * Get cls instance and make sure it's been activated
487          */
488         clp = (struct spanscls *)inp->inf_isintf;
489         if ((clp == NULL) || (clp->cls_ipnif == NULL))
490                 return (ENXIO);
491
492         /*
493          * Let arp know about this
494          */
495         spansarp_ipdact(clp);
496
497         /*
498          * Clear IP interface pointer
499          */
500         clp->cls_ipnif = NULL;
501         return (0);
502 }
503
504
505 /*
506  * Output IP Broadcast Packet
507  * 
508  * Called whenever an IP broadcast packet is sent to this interface.
509  *
510  * Arguments:
511  *      inp     pointer to IP network interface
512  *      m       pointer to packet buffer chain
513  *
514  * Returns:
515  *      0       packet sent successfully
516  *      errno   send failed - reason indicated
517  *
518  */
519 static int
520 spanscls_bcast_output(struct ip_nif *inp, KBuffer *m)
521 {
522         struct spans            *spp;
523         struct spanscls         *clp;
524         struct spanscls_hdr     *chp;
525         int                     err, space;
526
527         /*
528          * Get cls instance and make sure it's been activated
529          */
530         clp = (struct spanscls *)inp->inf_isintf;
531         if ((clp == NULL) || (clp->cls_ipnif == NULL)) {
532                 KB_FREEALL(m);
533                 return (ENETDOWN);
534         }
535
536         /*
537          * Make sure that we know our addresses
538          */
539         spp = clp->cls_spans;
540         if (spp->sp_addr.address_format != T_ATM_SPANS_ADDR) {
541                 KB_FREEALL(m);
542                 return (ENETDOWN);
543         }
544
545         /*
546          * See if there's room to add CLS header to front of packet.
547          */
548         KB_HEADROOM(m, space);
549         if (space < sizeof(struct spanscls_hdr)) {
550                 KBuffer         *n;
551
552                 /*
553                  * We have to allocate another buffer and tack it
554                  * onto the front of the packet
555                  */
556                 KB_ALLOCPKT(n, sizeof(struct spanscls_hdr),
557                         KB_F_NOWAIT, KB_T_HEADER);
558                 if (n == NULL) {
559                         KB_FREEALL(m);
560                         return (ENOBUFS);
561                 }
562                 KB_TAILALIGN(n, sizeof(struct spanscls_hdr));
563                 KB_LINKHEAD(n, m);
564                 m = n;
565         } else {
566                 /*
567                  * Header fits, just adjust buffer controls
568                  */
569                 KB_HEADADJ(m, sizeof(struct spanscls_hdr));
570         }
571
572         /*
573          * Now, build the CLS header
574          */
575         KB_DATASTART(m, chp, struct spanscls_hdr *);
576         spans_addr_copy(&spans_bcastaddr, &chp->ch_dst);
577         spans_addr_copy(spp->sp_addr.address, &chp->ch_src);
578         *(u_int *)&chp->ch_proto = *(u_int *)&spanscls_hdr.ch_proto;
579         *(u_int *)&chp->ch_dsap = *(u_int *)&spanscls_hdr.ch_dsap;
580         *(u_short *)&chp->ch_oui[1] = *(u_short *)&spanscls_hdr.ch_oui[1];
581         chp->ch_pid = htons(ETHERTYPE_IP);
582
583 #ifdef DIAGNOSTIC
584         if (spanscls_print)
585                 spanscls_pdu_print(clp, m, "output");
586 #endif
587
588         /*
589          * Finally, send the pdu via the CLS service
590          */
591         err = atm_cm_cpcs_data(clp->cls_conn, m);
592         if (err) {
593                 KB_FREEALL(m);
594                 return (ENOBUFS);
595         }
596
597         return (0);
598 }
599
600
601 /*
602  * Process VCC Input Data
603  * 
604  * All input packets received from CLS VCC lower layers are processed here.
605  *
606  * Arguments:
607  *      tok     connection token (pointer to CLS VCC control block)
608  *      m       pointer to input packet buffer chain
609  *
610  * Returns:
611  *      none
612  *
613  */
614 static void
615 spanscls_cpcs_data(void *tok, KBuffer *m)
616 {
617         struct spanscls *clp = tok;
618         struct spans    *spp = clp->cls_spans;
619         struct spanscls_hdr     *chp;
620         struct ip_nif   *inp;
621
622         /*
623          * Make sure we're ready
624          */
625         if ((clp->cls_state != CLS_OPEN) || (spp->sp_state != SPANS_ACTIVE)) {
626                 KB_FREEALL(m);
627                 return;
628         }
629
630 #ifdef DIAGNOSTIC
631         if (spanscls_print)
632                 spanscls_pdu_print(clp, m, "input");
633 #endif
634
635         /*
636          * Get CLS header into buffer
637          */
638         if (KB_LEN(m) < sizeof(struct spanscls_hdr)) {
639                 KB_PULLUP(m, sizeof(struct spanscls_hdr), m);
640                 if (m == NULL)
641                         return;
642         }
643         KB_DATASTART(m, chp, struct spanscls_hdr *);
644
645         /*
646          * Verify packet information
647          */
648         if ((*(u_int *)&chp->ch_proto != *(u_int *)&spanscls_hdr.ch_proto) ||
649             (*(u_int *)&chp->ch_dsap != *(u_int *)&spanscls_hdr.ch_dsap) ||
650             (*(u_short *)&chp->ch_oui[1] != 
651                                 *(u_short *)&spanscls_hdr.ch_oui[1])) {
652
653                 /*
654                  * Check for bridged PDU
655                  */
656                 if (bcmp((char *)&chp->ch_proto, (char *)spanscls_bridged, 
657                                 sizeof(spanscls_bridged))) {
658                         log(LOG_ERR, "spanscls_input: bad format\n");
659 #ifdef DIAGNOSTIC
660                         spanscls_pdu_print(clp, m, "input error"); 
661 #endif
662                 }
663
664                 KB_FREEALL(m);
665                 return;
666         }
667
668         /*
669          * Make sure packet is for us
670          */
671         if (spans_addr_cmp(&chp->ch_dst, spp->sp_addr.address) &&
672             spans_addr_cmp(&chp->ch_dst, &spans_bcastaddr)) {
673                 KB_FREEALL(m);
674                 return;
675         }
676
677         /*
678          * Do protocol processing
679          */
680         switch (ntohs(chp->ch_pid)) {
681
682         case ETHERTYPE_IP:
683                 /*
684                  * Drop CLS header
685                  */
686                 KB_HEADADJ(m, -sizeof(struct spanscls_hdr));
687                 KB_PLENADJ(m, -sizeof(struct spanscls_hdr));
688
689                 /*
690                  * Packet is ready for input to IP
691                  */
692                 if ((inp = clp->cls_ipnif) != NULL)
693                         (*inp->inf_ipinput)(inp, m);
694                 else
695                         KB_FREEALL(m);
696                 break;
697
698         case ETHERTYPE_ARP:
699                 spansarp_input(clp, m);
700                 break;
701
702         default:
703                 log(LOG_ERR, "spanscls_input: unknown protocol 0x%x\n",
704                         chp->ch_pid);
705                 KB_FREEALL(m);
706                 return;
707         }
708 }
709
710
711 /*
712  * Close a SPANS CLS VCC
713  * 
714  * This function will close a SPANS CLS VCC.
715  *
716  * Arguments:
717  *      clp     pointer to CLS instance
718  *      cause   pointer to cause code
719  *
720  * Returns:
721  *      none
722  *
723  */
724 void
725 spanscls_closevc(struct spanscls *clp, struct t_atm_cause *cause)
726 {
727         int     err;
728
729         /*
730          * Close VCC
731          */
732         if (clp->cls_conn) {
733                 err = atm_cm_release(clp->cls_conn, cause);
734                 if (err) {
735                         log(LOG_ERR, "spanscls_closevc: release err=%d\n", err);
736                 }
737                 clp->cls_conn = NULL;
738         }
739
740         clp->cls_state = CLS_CLOSED;
741 }
742
743
744 /*
745  * Process CLS VCC Connected Notification
746  * 
747  * Arguments:
748  *      toku    user's connection token (spanscls protocol block)
749  *
750  * Returns:
751  *      none
752  *
753  */
754 static void
755 spanscls_connected(void *toku)
756 {
757         /*
758          * We should never get one of these
759          */
760         log(LOG_ERR, "spanscls: unexpected connected event\n");
761 }
762
763
764 /*
765  * Process CLS VCC Cleared Notification
766  * 
767  * Arguments:
768  *      toku    user's connection token (spanscls protocol block)
769  *      cause   pointer to cause code
770  *
771  * Returns:
772  *      none
773  *
774  */
775 static void
776 spanscls_cleared(void *toku, struct t_atm_cause *cause)
777 {
778         struct spanscls *clp = (struct spanscls *)toku;
779
780         /*
781          * CLS VCC has been closed, so clean up our side
782          */
783         clp->cls_conn = NULL;
784         spanscls_closevc(clp, cause);
785 }
786
787
788 /*
789  * Get Connection's Application/Owner Name
790  * 
791  * Arguments:
792  *      tok     spanscls connection token
793  *
794  * Returns:
795  *      addr    pointer to string containing our name
796  *
797  */
798 static caddr_t
799 spanscls_getname(void *tok)
800 {
801         return ("SPANSCLS");
802 }
803
804
805 /*
806  * Print a SPANS CLS PDU
807  * 
808  * Arguments:
809  *      clp     pointer to cls instance
810  *      m       pointer to pdu buffer chain
811  *      msg     pointer to message string
812  *
813  * Returns:
814  *      none
815  *
816  */
817 static void
818 spanscls_pdu_print(struct spanscls *clp, KBuffer *m, char *msg)
819 {
820         char            buf[128];
821
822         ksnprintf(buf, sizeof(buf), "spanscls %s:\n", msg);
823         atm_pdu_print(m, buf);
824 }
825