2 * ===================================
3 * HARP | Host ATM Research Platform
4 * ===================================
7 * This Host ATM Research Platform ("HARP") file (the "Software") is
8 * made available by Network Computing Services, Inc. ("NetworkCS")
9 * "AS IS". NetworkCS does not provide maintenance, improvements or
10 * support of any kind.
12 * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
13 * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
14 * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
15 * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
16 * In no event shall NetworkCS be responsible for any damages, including
17 * but not limited to consequential damages, arising from or relating to
18 * any use of the Software or related support.
20 * Copyright 1994-1998 Network Computing Services, Inc.
22 * Copies of this Software may be made, however, the above copyright
23 * notice must be reproduced on all copies.
27 * SPANS Signalling Manager
28 * ---------------------------
30 * SPANS Connectionless Datagram Service (CLS) module
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/errno.h>
40 #include <sys/socket.h>
41 #include <sys/socketvar.h>
42 #include <sys/syslog.h>
43 #include <sys/kernel.h>
44 #include <sys/sysctl.h>
46 #include <netinet/in.h>
47 #include <netinet/if_ether.h>
48 #include <netatm/port.h>
49 #include <netatm/queue.h>
50 #include <netatm/atm.h>
51 #include <netatm/atm_sys.h>
52 #include <netatm/atm_sap.h>
53 #include <netatm/atm_cm.h>
54 #include <netatm/atm_if.h>
55 #include <netatm/atm_vc.h>
56 #include <netatm/atm_sigmgr.h>
57 #include <netatm/atm_stack.h>
58 #include <netatm/atm_pcb.h>
59 #include <netatm/atm_var.h>
61 #include <netatm/ipatm/ipatm_var.h>
62 #include <netatm/ipatm/ipatm_serv.h>
63 #include "spans_xdr.h"
64 #include <netatm/spans/spans_var.h>
65 #include <netatm/spans/spans_cls.h>
72 int spanscls_print = 0;
73 SYSCTL_INT(_net_harp_spans, OID_AUTO, spanscls_print, CTLFLAG_RW,
74 &spanscls_print, 0, "dump SPANS packets");
76 struct spanscls *spanscls_head = NULL;
78 struct spans_addr spans_bcastaddr = {
79 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }
82 struct spanscls_hdr spanscls_hdr = {
83 { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, /* dst */
84 { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, /* src */
86 0xaa, 0xaa, 0x03, { 0x00, 0x00, 0x00 }, 0 /* LLC SNAP */
93 static int spanscls_ipact(struct ip_nif *);
94 static int spanscls_ipdact(struct ip_nif *);
95 static int spanscls_bcast_output(struct ip_nif *, KBuffer *);
96 static void spanscls_cpcs_data(void *, KBuffer *);
97 static void spanscls_connected(void *);
98 static void spanscls_cleared(void *, struct t_atm_cause *);
99 static caddr_t spanscls_getname(void *);
100 static void spanscls_pdu_print(const struct spanscls *, const KBuffer *,
106 static uma_zone_t spanscls_zone;
108 static struct ip_serv spanscls_ipserv = {
117 spanscls_bcast_output,
119 {ATM_AAL5, ATM_ENC_NULL},
120 {ATM_AAL3_4, ATM_ENC_NULL}
124 static u_char spanscls_bridged[] = {
125 0x00, 0x00, 0x00, 0x00,
126 0xaa, 0xaa, 0x03, 0x00, 0x80, 0xc2 /* LLC SNAP */
129 static Atm_endpoint spanscls_endpt = {
147 static Atm_attributes spanscls_attr = {
149 CMAPI_CPCS, /* api */
210 T_ATM_NETWORK_CODING,
227 static struct t_atm_cause spanscls_cause = {
230 T_ATM_CAUSE_UNSPECIFIED_NORMAL,
236 * Process module loading
238 * Called whenever the spans module is initializing.
244 * 0 initialization successful
245 * errno initialization failed - reason indicated
253 spanscls_zone = uma_zcreate("spanscls", sizeof(struct spanscls),
254 NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
255 if (spanscls_zone == NULL)
256 panic("spanscls_zone");
259 * Fill in union fields
261 spanscls_attr.aal.v.aal4.forward_max_SDU_size = ATM_NIF_MTU;
262 spanscls_attr.aal.v.aal4.backward_max_SDU_size = ATM_NIF_MTU;
263 spanscls_attr.aal.v.aal4.SSCS_type = T_ATM_NULL;
264 spanscls_attr.aal.v.aal4.mid_low = 0;
265 spanscls_attr.aal.v.aal4.mid_high = 1023;
268 * Register our endpoint
270 err = atm_endpoint_register(&spanscls_endpt);
277 * Process module unloading notification
279 * Called whenever the spans module is about to be unloaded. All signalling
280 * instances will have been previously detached. All spanscls resources
301 * Nothing should be left here...
304 panic("spanscls_stop: bad state");
309 * De-register ourselves
311 (void) atm_endpoint_deregister(&spanscls_endpt);
314 * Free our storage pools
316 uma_zdestroy(spanscls_zone);
321 * Process signalling interface attach
323 * This function is called whenever a physical interface has been attached
324 * to spans. We will open the CLS PVC and await further events.
329 * spp pointer to spans signalling protocol instance
332 * 0 attach successful
333 * errno attach failed - reason indicated
340 struct spanscls *clp;
345 * Get a new cls control block
347 clp = uma_zalloc(spanscls_zone, M_WAITOK);
352 * Initialize some stuff
354 clp->cls_state = CLS_CLOSED;
355 clp->cls_spans = spp;
356 spp->sp_ipserv = &spanscls_ipserv;
359 * Fill out connection attributes
361 spanscls_attr.nif = spp->sp_pif->pif_nif;
362 spanscls_attr.traffic.v.forward.PCR_all_traffic = spp->sp_pif->pif_pcr;
363 spanscls_attr.traffic.v.backward.PCR_all_traffic = spp->sp_pif->pif_pcr;
364 spanscls_attr.called.addr.address_format = T_ATM_PVC_ADDR;
365 spanscls_attr.called.addr.address_length = sizeof(Atm_addr_pvc);
366 pvcp = (Atm_addr_pvc *)spanscls_attr.called.addr.address;
367 ATM_PVC_SET_VPI(pvcp, SPANS_CLS_VPI);
368 ATM_PVC_SET_VCI(pvcp, SPANS_CLS_VCI);
369 spanscls_attr.called.subaddr.address_format = T_ATM_ABSENT;
370 spanscls_attr.called.subaddr.address_length = 0;
373 * Create SPANS Connectionless Service (CLS) PVC
375 err = atm_cm_connect(&spanscls_endpt, clp, &spanscls_attr,
378 uma_zfree(spanscls_zone, clp);
383 * Set new state and link instance
385 clp->cls_state = CLS_OPEN;
386 LINK2TAIL(clp, struct spanscls, spanscls_head, cls_next);
394 * Process signalling interface detach
396 * This function is called whenever a physical interface has been detached
397 * from spans. We will close the CLS PVC and clean up everything.
402 * spp pointer to spans signalling protocol instance
412 struct spanscls *clp;
415 * Get our control block
422 * Just checking up on things...
425 panic("spanscls_detach: IP interface still active");
430 spanscls_closevc(clp, &spanscls_cause);
433 * Sever links and free server block, if possible
435 clp->cls_spans = NULL;
437 if (clp->cls_state == CLS_CLOSED) {
438 UNLINK(clp, struct spanscls, spanscls_head, cls_next);
439 uma_zfree(spanscls_zone, clp);
445 * Process IP Network Interface Activation
447 * Called whenever an IP network interface becomes active.
452 * inp pointer to IP network interface
455 * 0 command successful
456 * errno command failed - reason indicated
464 struct spanscls *clp;
467 * Get corresponding cls instance
469 spp = (struct spans *)inp->inf_nif->nif_pif->pif_siginst;
470 if ((spp == NULL) || ((clp = spp->sp_cls) == NULL))
474 * Make sure it's not already activated
480 * Set two-way links with IP world
482 clp->cls_ipnif = inp;
483 inp->inf_isintf = (caddr_t)clp;
486 * Tell arp about new interface
495 * Process IP Network Interface Deactivation
497 * Called whenever an IP network interface becomes inactive.
502 * inp pointer to IP network interface
505 * 0 command successful
506 * errno command failed - reason indicated
513 struct spanscls *clp;
516 * Get cls instance and make sure it's been activated
518 clp = (struct spanscls *)inp->inf_isintf;
519 if ((clp == NULL) || (clp->cls_ipnif == NULL))
523 * Let arp know about this
525 spansarp_ipdact(clp);
528 * Clear IP interface pointer
530 clp->cls_ipnif = NULL;
536 * Output IP Broadcast Packet
538 * Called whenever an IP broadcast packet is sent to this interface.
541 * inp pointer to IP network interface
542 * m pointer to packet buffer chain
545 * 0 packet sent successfully
546 * errno send failed - reason indicated
550 spanscls_bcast_output(inp, m)
555 struct spanscls *clp;
556 struct spanscls_hdr *chp;
560 * Get cls instance and make sure it's been activated
562 clp = (struct spanscls *)inp->inf_isintf;
563 if ((clp == NULL) || (clp->cls_ipnif == NULL)) {
569 * Make sure that we know our addresses
571 spp = clp->cls_spans;
572 if (spp->sp_addr.address_format != T_ATM_SPANS_ADDR) {
578 * See if there's room to add CLS header to front of packet.
580 KB_HEADROOM(m, space);
581 if (space < sizeof(struct spanscls_hdr)) {
585 * We have to allocate another buffer and tack it
586 * onto the front of the packet
588 KB_ALLOCPKT(n, sizeof(struct spanscls_hdr),
589 KB_F_NOWAIT, KB_T_HEADER);
594 KB_TAILALIGN(n, sizeof(struct spanscls_hdr));
599 * Header fits, just adjust buffer controls
601 KB_HEADADJ(m, sizeof(struct spanscls_hdr));
605 * Now, build the CLS header
607 KB_DATASTART(m, chp, struct spanscls_hdr *);
608 spans_addr_copy(&spans_bcastaddr, &chp->ch_dst);
609 spans_addr_copy(spp->sp_addr.address, &chp->ch_src);
610 *(u_int *)&chp->ch_proto = *(u_int *)&spanscls_hdr.ch_proto;
611 *(u_int *)&chp->ch_dsap = *(u_int *)&spanscls_hdr.ch_dsap;
612 *(u_short *)&chp->ch_oui[1] = *(u_short *)&spanscls_hdr.ch_oui[1];
613 chp->ch_pid = htons(ETHERTYPE_IP);
616 spanscls_pdu_print(clp, m, "output");
619 * Finally, send the pdu via the CLS service
621 err = atm_cm_cpcs_data(clp->cls_conn, m);
632 * Process VCC Input Data
634 * All input packets received from CLS VCC lower layers are processed here.
637 * tok connection token (pointer to CLS VCC control block)
638 * m pointer to input packet buffer chain
645 spanscls_cpcs_data(tok, m)
649 struct spanscls *clp = tok;
650 struct spans *spp = clp->cls_spans;
651 struct spanscls_hdr *chp;
655 * Make sure we're ready
657 if ((clp->cls_state != CLS_OPEN) || (spp->sp_state != SPANS_ACTIVE)) {
663 spanscls_pdu_print(clp, m, "input");
666 * Get CLS header into buffer
668 if (KB_LEN(m) < sizeof(struct spanscls_hdr)) {
669 KB_PULLUP(m, sizeof(struct spanscls_hdr), m);
673 KB_DATASTART(m, chp, struct spanscls_hdr *);
676 * Verify packet information
678 if ((*(u_int *)&chp->ch_proto != *(u_int *)&spanscls_hdr.ch_proto) ||
679 (*(u_int *)&chp->ch_dsap != *(u_int *)&spanscls_hdr.ch_dsap) ||
680 (*(u_short *)&chp->ch_oui[1] !=
681 *(u_short *)&spanscls_hdr.ch_oui[1])) {
684 * Check for bridged PDU
686 if (bcmp((char *)&chp->ch_proto, (char *)spanscls_bridged,
687 sizeof(spanscls_bridged))) {
688 log(LOG_ERR, "spanscls_input: bad format\n");
690 spanscls_pdu_print(clp, m, "input error");
698 * Make sure packet is for us
700 if (spans_addr_cmp(&chp->ch_dst, spp->sp_addr.address) &&
701 spans_addr_cmp(&chp->ch_dst, &spans_bcastaddr)) {
707 * Do protocol processing
709 switch (ntohs(chp->ch_pid)) {
715 KB_HEADADJ(m, -sizeof(struct spanscls_hdr));
716 KB_PLENADJ(m, -sizeof(struct spanscls_hdr));
719 * Packet is ready for input to IP
721 if ((inp = clp->cls_ipnif) != NULL)
722 (void) (*inp->inf_ipinput)(inp, m);
728 spansarp_input(clp, m);
732 log(LOG_ERR, "spanscls_input: unknown protocol 0x%x\n",
741 * Close a SPANS CLS VCC
743 * This function will close a SPANS CLS VCC.
746 * clp pointer to CLS instance
747 * cause pointer to cause code
754 spanscls_closevc(clp, cause)
755 struct spanscls *clp;
756 struct t_atm_cause *cause;
764 err = atm_cm_release(clp->cls_conn, cause);
766 log(LOG_ERR, "spanscls_closevc: release err=%d\n", err);
768 clp->cls_conn = NULL;
771 clp->cls_state = CLS_CLOSED;
776 * Process CLS VCC Connected Notification
779 * toku user's connection token (spanscls protocol block)
786 spanscls_connected(toku)
790 * We should never get one of these
792 log(LOG_ERR, "spanscls: unexpected connected event\n");
797 * Process CLS VCC Cleared Notification
800 * toku user's connection token (spanscls protocol block)
801 * cause pointer to cause code
808 spanscls_cleared(toku, cause)
810 struct t_atm_cause *cause;
812 struct spanscls *clp = (struct spanscls *)toku;
815 * CLS VCC has been closed, so clean up our side
817 clp->cls_conn = NULL;
818 spanscls_closevc(clp, cause);
823 * Get Connection's Application/Owner Name
826 * tok spanscls connection token
829 * addr pointer to string containing our name
833 spanscls_getname(tok)
840 * Print a SPANS CLS PDU
843 * clp pointer to cls instance
844 * m pointer to pdu buffer chain
845 * msg pointer to message string
852 spanscls_pdu_print(const struct spanscls *clp, const KBuffer *m,
857 snprintf(buf, sizeof(buf), "spanscls %s:\n", msg);
858 atm_pdu_print(m, buf);