3 * ===================================
4 * HARP | Host ATM Research Platform
5 * ===================================
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.
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.
21 * Copyright 1994-1998 Network Computing Services, Inc.
23 * Copies of this Software may be made, however, the above copyright
24 * notice must be reproduced on all copies.
26 * @(#) $FreeBSD: src/sys/netatm/spans/spans_cls.c,v 1.6 1999/08/28 00:48:49 peter Exp $
27 * @(#) $DragonFly: src/sys/netproto/atm/spans/spans_cls.c,v 1.8 2006/12/20 18:14:43 dillon Exp $
31 * SPANS Signalling Manager
32 * ---------------------------
34 * SPANS Connectionless Datagram Service (CLS) module
38 #include <netproto/atm/kern_include.h>
40 #include <netproto/atm/ipatm/ipatm_var.h>
41 #include <netproto/atm/ipatm/ipatm_serv.h>
42 #include "spans_xdr.h"
43 #include "spans_var.h"
44 #include "spans_cls.h"
49 int spanscls_print
= 0;
51 struct spanscls
*spanscls_head
= NULL
;
53 struct spans_addr spans_bcastaddr
= {
54 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }
57 struct spanscls_hdr spanscls_hdr
= {
58 { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, /* dst */
59 { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, /* src */
61 0xaa, 0xaa, 0x03, { 0x00, 0x00, 0x00 }, 0 /* LLC SNAP */
68 static int spanscls_ipact (struct ip_nif
*);
69 static int spanscls_ipdact (struct ip_nif
*);
70 static int spanscls_bcast_output (struct ip_nif
*, KBuffer
*);
71 static void spanscls_cpcs_data (void *, KBuffer
*);
72 static void spanscls_connected (void *);
73 static void spanscls_cleared (void *, struct t_atm_cause
*);
74 static caddr_t
spanscls_getname (void *);
75 static void spanscls_pdu_print (struct spanscls
*, KBuffer
*,
81 static struct sp_info spanscls_pool
= {
82 "spans cls pool", /* si_name */
83 sizeof(struct spanscls
), /* si_blksiz */
88 static struct ip_serv spanscls_ipserv
= {
97 spanscls_bcast_output
,
99 {ATM_AAL5
, ATM_ENC_NULL
},
100 {ATM_AAL3_4
, ATM_ENC_NULL
}
104 static u_char spanscls_bridged
[] = {
105 0x00, 0x00, 0x00, 0x00,
106 0xaa, 0xaa, 0x03, 0x00, 0x80, 0xc2 /* LLC SNAP */
109 static Atm_endpoint spanscls_endpt
= {
127 static Atm_attributes spanscls_attr
= {
129 CMAPI_CPCS
, /* api */
190 T_ATM_NETWORK_CODING
,
207 static struct t_atm_cause spanscls_cause
= {
210 T_ATM_CAUSE_UNSPECIFIED_NORMAL
,
216 * Process module loading
218 * Called whenever the spans module is initializing.
224 * 0 initialization successful
225 * errno initialization failed - reason indicated
234 * Fill in union fields
236 spanscls_attr
.aal
.v
.aal4
.forward_max_SDU_size
= ATM_NIF_MTU
;
237 spanscls_attr
.aal
.v
.aal4
.backward_max_SDU_size
= ATM_NIF_MTU
;
238 spanscls_attr
.aal
.v
.aal4
.SSCS_type
= T_ATM_NULL
;
239 spanscls_attr
.aal
.v
.aal4
.mid_low
= 0;
240 spanscls_attr
.aal
.v
.aal4
.mid_high
= 1023;
243 * Register our endpoint
245 err
= atm_endpoint_register(&spanscls_endpt
);
252 * Process module unloading notification
254 * Called whenever the spans module is about to be unloaded. All signalling
255 * instances will have been previously detached. All spanscls resources
276 * Nothing should be left here...
279 panic("spanscls_stop: bad state");
284 * De-register ourselves
286 atm_endpoint_deregister(&spanscls_endpt
);
289 * Free our storage pools
291 atm_release_pool(&spanscls_pool
);
296 * Process signalling interface attach
298 * This function is called whenever a physical interface has been attached
299 * to spans. We will open the CLS PVC and await further events.
301 * Called from a critical section.
304 * spp pointer to spans signalling protocol instance
307 * 0 attach successful
308 * errno attach failed - reason indicated
312 spanscls_attach(struct spans
*spp
)
314 struct spanscls
*clp
;
319 * Get a new cls control block
321 clp
= (struct spanscls
*)atm_allocate(&spanscls_pool
);
326 * Initialize some stuff
328 clp
->cls_state
= CLS_CLOSED
;
329 clp
->cls_spans
= spp
;
330 spp
->sp_ipserv
= &spanscls_ipserv
;
333 * Fill out connection attributes
335 spanscls_attr
.nif
= spp
->sp_pif
->pif_nif
;
336 spanscls_attr
.traffic
.v
.forward
.PCR_all_traffic
= spp
->sp_pif
->pif_pcr
;
337 spanscls_attr
.traffic
.v
.backward
.PCR_all_traffic
= spp
->sp_pif
->pif_pcr
;
338 spanscls_attr
.called
.addr
.address_format
= T_ATM_PVC_ADDR
;
339 spanscls_attr
.called
.addr
.address_length
= sizeof(Atm_addr_pvc
);
340 pvcp
= (Atm_addr_pvc
*)spanscls_attr
.called
.addr
.address
;
341 ATM_PVC_SET_VPI(pvcp
, SPANS_CLS_VPI
);
342 ATM_PVC_SET_VCI(pvcp
, SPANS_CLS_VCI
);
343 spanscls_attr
.called
.subaddr
.address_format
= T_ATM_ABSENT
;
344 spanscls_attr
.called
.subaddr
.address_length
= 0;
347 * Create SPANS Connectionless Service (CLS) PVC
349 err
= atm_cm_connect(&spanscls_endpt
, clp
, &spanscls_attr
,
352 atm_free((caddr_t
)clp
);
357 * Set new state and link instance
359 clp
->cls_state
= CLS_OPEN
;
360 LINK2TAIL(clp
, struct spanscls
, spanscls_head
, cls_next
);
368 * Process signalling interface detach
370 * This function is called whenever a physical interface has been detached
371 * from spans. We will close the CLS PVC and clean up everything.
373 * Called from a critical section.
376 * spp pointer to spans signalling protocol instance
383 spanscls_detach(struct spans
*spp
)
385 struct spanscls
*clp
;
388 * Get our control block
395 * Just checking up on things...
398 panic("spanscls_detach: IP interface still active");
403 spanscls_closevc(clp
, &spanscls_cause
);
406 * Sever links and free server block, if possible
408 clp
->cls_spans
= NULL
;
410 if (clp
->cls_state
== CLS_CLOSED
) {
411 UNLINK(clp
, struct spanscls
, spanscls_head
, cls_next
);
412 atm_free((caddr_t
)clp
);
418 * Process IP Network Interface Activation
420 * Called whenever an IP network interface becomes active.
422 * Called from a critical section.
425 * inp pointer to IP network interface
428 * 0 command successful
429 * errno command failed - reason indicated
433 spanscls_ipact(struct ip_nif
*inp
)
436 struct spanscls
*clp
;
439 * Get corresponding cls instance
441 spp
= (struct spans
*)inp
->inf_nif
->nif_pif
->pif_siginst
;
442 if ((spp
== NULL
) || ((clp
= spp
->sp_cls
) == NULL
))
446 * Make sure it's not already activated
452 * Set two-way links with IP world
454 clp
->cls_ipnif
= inp
;
455 inp
->inf_isintf
= (caddr_t
)clp
;
458 * Tell arp about new interface
467 * Process IP Network Interface Deactivation
469 * Called whenever an IP network interface becomes inactive.
471 * Called from a critical section.
474 * inp pointer to IP network interface
477 * 0 command successful
478 * errno command failed - reason indicated
482 spanscls_ipdact(struct ip_nif
*inp
)
484 struct spanscls
*clp
;
487 * Get cls instance and make sure it's been activated
489 clp
= (struct spanscls
*)inp
->inf_isintf
;
490 if ((clp
== NULL
) || (clp
->cls_ipnif
== NULL
))
494 * Let arp know about this
496 spansarp_ipdact(clp
);
499 * Clear IP interface pointer
501 clp
->cls_ipnif
= NULL
;
507 * Output IP Broadcast Packet
509 * Called whenever an IP broadcast packet is sent to this interface.
512 * inp pointer to IP network interface
513 * m pointer to packet buffer chain
516 * 0 packet sent successfully
517 * errno send failed - reason indicated
521 spanscls_bcast_output(struct ip_nif
*inp
, KBuffer
*m
)
524 struct spanscls
*clp
;
525 struct spanscls_hdr
*chp
;
529 * Get cls instance and make sure it's been activated
531 clp
= (struct spanscls
*)inp
->inf_isintf
;
532 if ((clp
== NULL
) || (clp
->cls_ipnif
== NULL
)) {
538 * Make sure that we know our addresses
540 spp
= clp
->cls_spans
;
541 if (spp
->sp_addr
.address_format
!= T_ATM_SPANS_ADDR
) {
547 * See if there's room to add CLS header to front of packet.
549 KB_HEADROOM(m
, space
);
550 if (space
< sizeof(struct spanscls_hdr
)) {
554 * We have to allocate another buffer and tack it
555 * onto the front of the packet
557 KB_ALLOCPKT(n
, sizeof(struct spanscls_hdr
),
558 KB_F_NOWAIT
, KB_T_HEADER
);
563 KB_TAILALIGN(n
, sizeof(struct spanscls_hdr
));
568 * Header fits, just adjust buffer controls
570 KB_HEADADJ(m
, sizeof(struct spanscls_hdr
));
574 * Now, build the CLS header
576 KB_DATASTART(m
, chp
, struct spanscls_hdr
*);
577 spans_addr_copy(&spans_bcastaddr
, &chp
->ch_dst
);
578 spans_addr_copy(spp
->sp_addr
.address
, &chp
->ch_src
);
579 *(u_int
*)&chp
->ch_proto
= *(u_int
*)&spanscls_hdr
.ch_proto
;
580 *(u_int
*)&chp
->ch_dsap
= *(u_int
*)&spanscls_hdr
.ch_dsap
;
581 *(u_short
*)&chp
->ch_oui
[1] = *(u_short
*)&spanscls_hdr
.ch_oui
[1];
582 chp
->ch_pid
= htons(ETHERTYPE_IP
);
586 spanscls_pdu_print(clp
, m
, "output");
590 * Finally, send the pdu via the CLS service
592 err
= atm_cm_cpcs_data(clp
->cls_conn
, m
);
603 * Process VCC Input Data
605 * All input packets received from CLS VCC lower layers are processed here.
608 * tok connection token (pointer to CLS VCC control block)
609 * m pointer to input packet buffer chain
616 spanscls_cpcs_data(void *tok
, KBuffer
*m
)
618 struct spanscls
*clp
= tok
;
619 struct spans
*spp
= clp
->cls_spans
;
620 struct spanscls_hdr
*chp
;
624 * Make sure we're ready
626 if ((clp
->cls_state
!= CLS_OPEN
) || (spp
->sp_state
!= SPANS_ACTIVE
)) {
633 spanscls_pdu_print(clp
, m
, "input");
637 * Get CLS header into buffer
639 if (KB_LEN(m
) < sizeof(struct spanscls_hdr
)) {
640 KB_PULLUP(m
, sizeof(struct spanscls_hdr
), m
);
644 KB_DATASTART(m
, chp
, struct spanscls_hdr
*);
647 * Verify packet information
649 if ((*(u_int
*)&chp
->ch_proto
!= *(u_int
*)&spanscls_hdr
.ch_proto
) ||
650 (*(u_int
*)&chp
->ch_dsap
!= *(u_int
*)&spanscls_hdr
.ch_dsap
) ||
651 (*(u_short
*)&chp
->ch_oui
[1] !=
652 *(u_short
*)&spanscls_hdr
.ch_oui
[1])) {
655 * Check for bridged PDU
657 if (bcmp((char *)&chp
->ch_proto
, (char *)spanscls_bridged
,
658 sizeof(spanscls_bridged
))) {
659 log(LOG_ERR
, "spanscls_input: bad format\n");
661 spanscls_pdu_print(clp
, m
, "input error");
670 * Make sure packet is for us
672 if (spans_addr_cmp(&chp
->ch_dst
, spp
->sp_addr
.address
) &&
673 spans_addr_cmp(&chp
->ch_dst
, &spans_bcastaddr
)) {
679 * Do protocol processing
681 switch (ntohs(chp
->ch_pid
)) {
687 KB_HEADADJ(m
, -sizeof(struct spanscls_hdr
));
688 KB_PLENADJ(m
, -sizeof(struct spanscls_hdr
));
691 * Packet is ready for input to IP
693 if ((inp
= clp
->cls_ipnif
) != NULL
)
694 (*inp
->inf_ipinput
)(inp
, m
);
700 spansarp_input(clp
, m
);
704 log(LOG_ERR
, "spanscls_input: unknown protocol 0x%x\n",
713 * Close a SPANS CLS VCC
715 * This function will close a SPANS CLS VCC.
718 * clp pointer to CLS instance
719 * cause pointer to cause code
726 spanscls_closevc(struct spanscls
*clp
, struct t_atm_cause
*cause
)
734 err
= atm_cm_release(clp
->cls_conn
, cause
);
736 log(LOG_ERR
, "spanscls_closevc: release err=%d\n", err
);
738 clp
->cls_conn
= NULL
;
741 clp
->cls_state
= CLS_CLOSED
;
746 * Process CLS VCC Connected Notification
749 * toku user's connection token (spanscls protocol block)
756 spanscls_connected(void *toku
)
759 * We should never get one of these
761 log(LOG_ERR
, "spanscls: unexpected connected event\n");
766 * Process CLS VCC Cleared Notification
769 * toku user's connection token (spanscls protocol block)
770 * cause pointer to cause code
777 spanscls_cleared(void *toku
, struct t_atm_cause
*cause
)
779 struct spanscls
*clp
= (struct spanscls
*)toku
;
782 * CLS VCC has been closed, so clean up our side
784 clp
->cls_conn
= NULL
;
785 spanscls_closevc(clp
, cause
);
790 * Get Connection's Application/Owner Name
793 * tok spanscls connection token
796 * addr pointer to string containing our name
800 spanscls_getname(void *tok
)
807 * Print a SPANS CLS PDU
810 * clp pointer to cls instance
811 * m pointer to pdu buffer chain
812 * msg pointer to message string
819 spanscls_pdu_print(struct spanscls
*clp
, KBuffer
*m
, char *msg
)
823 ksnprintf(buf
, sizeof(buf
), "spanscls %s:\n", msg
);
824 atm_pdu_print(m
, buf
);