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/usr.sbin/atm/scspd/scsp_input.c,v 1.3 1999/08/28 01:15:33 peter Exp $
27 * @(#) $DragonFly: src/usr.sbin/atm/scspd/scsp_input.c,v 1.3 2003/11/03 19:31:35 eirikn Exp $
31 * Server Cache Synchronization Protocol (SCSP) Support
32 * ----------------------------------------------------
34 * Input packet processing
38 #include <sys/types.h>
39 #include <sys/param.h>
40 #include <sys/socket.h>
41 #include <net/ethernet.h>
43 #include <netinet/in.h>
44 #include <netatm/port.h>
45 #include <netatm/queue.h>
46 #include <netatm/atm.h>
47 #include <netatm/atm_if.h>
48 #include <netatm/atm_sap.h>
49 #include <netatm/atm_sys.h>
50 #include <netatm/atm_ioctl.h>
63 static int scsp_parse_atmarp(char *, int, Scsp_atmarp_csa **);
69 * This routine is provided to handle long integers that may not
70 * be word-aligned in the input buffer.
73 * cp pointer to long int in message
76 * int long int in host order
87 * Read the long out of the input buffer
90 for (i = 0; i < sizeof(u_long); i++)
94 * Return the value in host order
101 * Free an SCSP Cache Alignment message in internal format
104 * cap pointer to CA message
114 Scsp_csa *csap, *ncsap;
117 * Return if there's nothing to free
119 if (cap == (Scsp_ca *)0)
123 * Free the CSAS records
125 for (csap = cap->ca_csa_rec; csap; csap = ncsap) {
130 * Free the CA message structure
137 * Free an SCSP Cache State Update Request, Cache State Update Reply,
138 * or Cache State Update Solicit message in internal format
141 * csup pointer to CSU message
151 Scsp_csa *csap, *ncsap;
154 * Return if there's nothing to free
156 if (csup == (Scsp_csu_msg *)0)
160 * Free the CSA records
162 for (csap = csup->csu_csa_rec; csap; csap = ncsap) {
168 * Free the CSU message structure
175 * Free an SCSP Hello message in internal format
178 * hp pointer to Hello message
189 * Return if there's nothing to free
191 if (hp == (Scsp_hello *)0)
195 * Free the Hello message structure
202 * Free an SCSP message in internal format
205 * msg pointer to input packet
215 Scsp_ext *exp, *nexp;
218 * Return if there's nothing to free
220 if (msg == (Scsp_msg *)0)
224 * Free the message body
226 switch(msg->sc_msg_type) {
228 scsp_free_ca(msg->sc_ca);
230 case SCSP_CSU_REQ_MSG:
231 case SCSP_CSU_REPLY_MSG:
233 scsp_free_csu(msg->sc_csu_msg);
236 scsp_free_hello(msg->sc_hello);
241 * Free any extensions
243 for (exp = msg->sc_ext; exp; exp = nexp) {
249 * Free the message structure
256 * Parse a Sender or Receiver ID
260 * id_len length of ID
261 * idp pointer to structure to receive the ID
264 * 0 input was invalid
265 * else length of ID processed
269 scsp_parse_id(buff, id_len, idp)
278 id_len == 0 || id_len > SCSP_MAX_ID_LEN ||
286 idp->id_len = id_len;
291 UM_COPY(buff, idp->id, id_len);
294 * Return the ID length
301 * Parse the Mandatory Common Part of an SCSP input packet
304 * buff pointer to mandatory common part
305 * pdu_len length of input packet
306 * mcp pointer to location of MCP in decoded record
309 * 0 input was invalid
310 * else length of MCP in message
314 scsp_parse_mcp(buff, pdu_len, mcp)
321 struct scsp_nmcp *smp;
324 * Get the protocol ID
326 smp = (struct scsp_nmcp *)buff;
327 mcp->pid = ntohs(smp->sm_pid);
328 if (mcp->pid < SCSP_PROTO_ATMARP ||
329 mcp->pid > SCSP_PROTO_LNNI) {
330 /* Protocol ID is invalid */
335 * Get the server group ID
337 mcp->sgid = ntohs(smp->sm_sgid);
342 mcp->flags = ntohs(smp->sm_flags);
345 * Get the sender ID and length
347 idp = (u_char *) ((caddr_t)smp + sizeof(struct scsp_nmcp));
348 len = scsp_parse_id(idp, smp->sm_sid_len, &mcp->sid);
354 * Get the receiver ID and length
357 len = scsp_parse_id(idp, smp->sm_rid_len, &mcp->rid);
363 * Get the record count
365 mcp->rec_cnt = ntohs(smp->sm_rec_cnt);
368 * Return the length of data we processed
370 return(sizeof(struct scsp_nmcp) + smp->sm_sid_len +
382 * buff pointer to Extension
383 * pdu_len length of buffer
384 * expp pointer to location to receive pointer to the Extension
387 * 0 input was invalid
388 * else length of Extension processed
392 scsp_parse_ext(buff, pdu_len, expp)
398 struct scsp_next *sep;
402 * Get memory for the extension
404 sep = (struct scsp_next *)buff;
405 len = sizeof(Scsp_ext) + ntohs(sep->se_len);
406 exp = (Scsp_ext *)UM_ALLOC(len);
415 exp->type = ntohs(sep->se_type);
420 exp->len = ntohs(sep->se_len);
426 UM_COPY((caddr_t)sep + sizeof(struct scsp_next),
427 (caddr_t)exp + sizeof(Scsp_ext),
432 * Save a pointer to the extension and return the
433 * number of bytes processed
436 return(sizeof(struct scsp_next) + exp->len);
447 * Parse a Cache State Advertisement or Cache State Advertisement
451 * buff pointer to CSA or CSAS record
452 * pdu_len length of input packet
453 * csapp pointer to location to put pointer to CSA or CSAS
456 * 0 input was invalid
457 * else length of record processed
461 scsp_parse_csa(buff, pdu_len, csapp)
468 struct scsp_ncsa *scp;
469 Scsp_csa *csap = NULL;
472 * Check the record length
474 scp = (struct scsp_ncsa *)buff;
475 if (ntohs(scp->scs_len) < (sizeof(struct scsp_ncsa) +
476 scp->scs_ck_len + scp->scs_oid_len)) {
481 * Get memory for the returned structure
483 len = sizeof(Scsp_csa) + ntohs(scp->scs_len) -
484 sizeof(struct scsp_ncsa) - scp->scs_ck_len -
486 csap = (Scsp_csa *)UM_ALLOC(len);
495 csap->hops = ntohs(scp->scs_hop_cnt);
500 csap->null = (ntohs(scp->scs_nfill) & SCSP_CSAS_NULL) != 0;
503 * Get the sequence number
505 csap->seq = get_long((u_char *)&scp->scs_seq);
510 if (scp->scs_ck_len == 0 ||
511 scp->scs_ck_len > SCSP_MAX_KEY_LEN) {
514 csap->key.key_len = scp->scs_ck_len;
515 idp = (char *) ((caddr_t)scp + sizeof(struct scsp_ncsa));
516 UM_COPY(idp, csap->key.key, scp->scs_ck_len);
519 * Get the originator ID
521 idp += scp->scs_ck_len;
522 len = scsp_parse_id(idp, scp->scs_oid_len, &csap->oid);
528 * Get the protocol-specific data, if present
530 len = ntohs(scp->scs_len) - (sizeof(struct scsp_ncsa) +
531 scp->scs_ck_len + scp->scs_oid_len);
533 idp += scp->scs_oid_len;
534 len = scsp_parse_atmarp(idp, len, &csap->atmarp_data);
540 * Set a pointer to the MCP and return the length
541 * of data we processed
544 return(ntohs(scp->scs_len));
554 * Parse a Cache Alignment message
557 * buff pointer to start of CA in message
558 * pdu_len length of input packet
559 * capp pointer to location to put pointer to CA message
562 * 0 input was invalid
563 * else length of CA message processed
567 scsp_parse_ca(buff, pdu_len, capp)
572 int i, len, proc_len;
573 struct scsp_nca *scap;
578 * Get memory for the returned structure
580 scap = (struct scsp_nca *)buff;
581 cap = (Scsp_ca *)UM_ALLOC(sizeof(Scsp_ca));
585 UM_ZERO(cap, sizeof(Scsp_ca));
588 * Get the sequence number
590 cap->ca_seq = get_long((u_char *)&scap->sca_seq);
591 proc_len = sizeof(scap->sca_seq);
592 buff += sizeof(scap->sca_seq);
595 * Process the mandatory common part of the message
597 len = scsp_parse_mcp(buff,
608 cap->ca_m = (cap->ca_mcp.flags & SCSP_CA_M) != 0;
609 cap->ca_i = (cap->ca_mcp.flags & SCSP_CA_I) != 0;
610 cap->ca_o = (cap->ca_mcp.flags & SCSP_CA_O) != 0;
613 * Get the CSAS records from the message
615 for (i = 0, csapp = &cap->ca_csa_rec; i < cap->ca_mcp.rec_cnt;
616 i++, csapp = &(*csapp)->next) {
617 len = scsp_parse_csa(buff, pdu_len - proc_len, csapp);
623 * Set the address of the CA message and
624 * return the length of processed data
637 * Parse the ATMARP-specific part of a CSA record
640 * buff pointer to ATMARP part of CSU message
641 * pdu_len length of data to process
642 * acspp pointer to location to put pointer to CSU message
645 * 0 input was invalid
646 * else length of CSU Req message processed
650 scsp_parse_atmarp(buff, pdu_len, acspp)
653 Scsp_atmarp_csa **acspp;
656 struct scsp_atmarp_ncsa *sacp;
657 Scsp_atmarp_csa *acsp = NULL;
660 * Initial packet verification
662 sacp = (struct scsp_atmarp_ncsa *)buff;
663 if ((sacp->sa_hrd != ntohs(ARP_ATMFORUM)) ||
664 (sacp->sa_pro != ntohs(ETHERTYPE_IP)))
668 * Get memory for the returned structure
670 acsp = (Scsp_atmarp_csa *)UM_ALLOC(sizeof(Scsp_atmarp_csa));
674 UM_ZERO(acsp, sizeof(Scsp_atmarp_csa));
679 acsp->sa_state = sacp->sa_state;
680 proc_len = sizeof(struct scsp_atmarp_ncsa);
683 * Verify/gather source ATM address
685 acsp->sa_sha.address_format = T_ATM_ABSENT;
686 acsp->sa_sha.address_length = 0;
687 if ((len = (sacp->sa_shtl & ARP_TL_LMASK)) != 0) {
688 if (sacp->sa_shtl & ARP_TL_E164) {
689 if (len > sizeof(Atm_addr_e164))
691 acsp->sa_sha.address_format = T_ATM_E164_ADDR;
693 if (len != sizeof(Atm_addr_nsap))
695 acsp->sa_sha.address_format = T_ATM_ENDSYS_ADDR;
697 acsp->sa_sha.address_length = len;
698 if (pdu_len < proc_len + len)
700 UM_COPY(&buff[proc_len], (char *)acsp->sa_sha.address,
706 * Verify/gather source ATM subaddress
708 acsp->sa_ssa.address_format = T_ATM_ABSENT;
709 acsp->sa_ssa.address_length = 0;
710 if ((len = (sacp->sa_sstl & ARP_TL_LMASK)) != 0) {
711 if (((sacp->sa_sstl & ARP_TL_TMASK) != ARP_TL_NSAPA) ||
712 (len != sizeof(Atm_addr_nsap)))
714 acsp->sa_ssa.address_format = T_ATM_ENDSYS_ADDR;
715 acsp->sa_ssa.address_length = len;
716 if (pdu_len < proc_len + len)
718 UM_COPY(&buff[proc_len], (char *)acsp->sa_ssa.address,
724 * Verify/gather source IP address
726 if ((len = sacp->sa_spln) != 0) {
727 if (len != sizeof(struct in_addr))
729 if (pdu_len < proc_len + len)
731 UM_COPY(&buff[proc_len], (char *)&acsp->sa_spa, len);
734 acsp->sa_spa.s_addr = 0;
738 * Verify/gather target ATM address
740 acsp->sa_tha.address_format = T_ATM_ABSENT;
741 acsp->sa_tha.address_length = 0;
742 if ((len = (sacp->sa_thtl & ARP_TL_LMASK)) != 0) {
743 if (sacp->sa_thtl & ARP_TL_E164) {
744 if (len > sizeof(Atm_addr_e164))
746 acsp->sa_tha.address_format = T_ATM_E164_ADDR;
748 if (len != sizeof(Atm_addr_nsap))
750 acsp->sa_tha.address_format = T_ATM_ENDSYS_ADDR;
752 acsp->sa_tha.address_length = len;
753 if (pdu_len < proc_len + len)
755 UM_COPY(&buff[proc_len], (char *)acsp->sa_tha.address,
761 * Verify/gather target ATM subaddress
763 acsp->sa_tsa.address_format = T_ATM_ABSENT;
764 acsp->sa_tsa.address_length = 0;
765 if ((len = (sacp->sa_tstl & ARP_TL_LMASK)) != 0) {
766 if (((sacp->sa_tstl & ARP_TL_TMASK) != ARP_TL_NSAPA) ||
767 (len != sizeof(Atm_addr_nsap)))
769 acsp->sa_tsa.address_format = T_ATM_ENDSYS_ADDR;
770 acsp->sa_tsa.address_length = len;
771 if (pdu_len < proc_len + len)
773 UM_COPY(&buff[proc_len], (char *)acsp->sa_tsa.address,
779 * Verify/gather target IP address
781 if ((len = sacp->sa_tpln) != 0) {
782 if (len != sizeof(struct in_addr))
784 if (pdu_len < proc_len + len)
786 UM_COPY(&buff[proc_len], (char *)&acsp->sa_tpa, len);
789 acsp->sa_tpa.s_addr = 0;
793 * Verify packet length
795 if (proc_len != pdu_len)
809 * Parse a Cache State Update Request, Cache State Update Reply, or
810 * Cache State Update Solicit message. These all have the same format,
811 * a Mandatory Common Part followed by a number of CSA or CSAS records.
814 * buff pointer to start of CSU message
815 * pdu_len length of input packet
816 * csupp pointer to location to put pointer to CSU message
819 * 0 input was invalid
820 * else length of CSU Req message processed
824 scsp_parse_csu(buff, pdu_len, csupp)
827 Scsp_csu_msg **csupp;
829 int i, len, proc_len;
834 * Get memory for the returned structure
836 csup = (Scsp_csu_msg *)UM_ALLOC(sizeof(Scsp_csu_msg));
840 UM_ZERO(csup, sizeof(Scsp_csu_msg));
843 * Process the mandatory common part of the message
845 len = scsp_parse_mcp(buff, pdu_len, &csup->csu_mcp);
852 * Get the CSAS records from the message
854 for (i = 0, csapp = &csup->csu_csa_rec;
855 i < csup->csu_mcp.rec_cnt;
856 i++, csapp = &(*csapp)->next) {
857 len = scsp_parse_csa(buff, pdu_len - proc_len, csapp);
863 * Set the address of the CSU Req message and
864 * return the length of processed data
877 * Parse a Hello message
880 * buff pointer to start of Hello in message
881 * pdu_len length of input packet
882 * hpp pointer to location to put pointer to Hello message
885 * 0 input was invalid
886 * else length of Hello message processed
890 scsp_parse_hello(buff, pdu_len, hpp)
895 int i, len, proc_len;
896 struct scsp_nhello *shp = (struct scsp_nhello *)buff;
902 * Get memory for the returned structure
904 hp = (Scsp_hello *)UM_ALLOC(sizeof(Scsp_hello));
908 UM_ZERO(hp, sizeof(Scsp_hello));
911 * Get the hello interval
913 hp->hello_int = ntohs(shp->sch_hi);
916 * Get the dead factor
918 hp->dead_factor = ntohs(shp->sch_df);
923 hp->family_id = ntohs(shp->sch_fid);
926 * Process the mandatory common part of the message
928 proc_len = sizeof(struct scsp_nhello) -
929 sizeof(struct scsp_nmcp);
931 len = scsp_parse_mcp(buff, pdu_len - proc_len,
939 * Get additional receiver ID records from the message
941 for (i = 0, ridpp = &hp->hello_mcp.rid.next;
942 i < hp->hello_mcp.rec_cnt;
943 i++, ridpp = &idp->next) {
944 idp = (Scsp_id *)UM_ALLOC(sizeof(Scsp_id));
948 UM_ZERO(idp, sizeof(Scsp_id));
949 len = scsp_parse_id(buff,
950 hp->hello_mcp.rid.id_len,
962 * Set the address of the CA message and
963 * return the length of processed data
976 * Parse an SCSP input packet
979 * buff pointer to input packet
980 * pdu_len length of input packet
983 * NULL input packet was invalid
984 * else pointer to packet in internal format
988 scsp_parse_msg(buff, pdu_len)
992 int ext_off, len, plen;
993 struct scsp_nhdr *shp;
994 Scsp_msg *msg = (Scsp_msg *)0;
998 * Check the message checksum
1000 if (ip_checksum(buff, pdu_len) != 0) {
1002 * Checksum was bad--discard the message
1008 * Allocate storage for the message
1010 msg = (Scsp_msg *)UM_ALLOC(sizeof(Scsp_msg));
1014 UM_ZERO(msg, sizeof(Scsp_msg));
1017 * Decode the fixed header
1021 shp = (struct scsp_nhdr *)buff;
1022 if (shp->sh_ver != SCSP_VER_1)
1026 * Get the message type
1028 msg->sc_msg_type = shp->sh_type;
1031 * Get and check the length
1033 len = ntohs(shp->sh_len);
1038 * Get the extension offset
1040 ext_off = ntohs(shp->sh_ext_off);
1043 * Decode the body of the message, depending on the type
1045 buff += sizeof(struct scsp_nhdr);
1046 len -= sizeof(struct scsp_nhdr);
1047 switch(msg->sc_msg_type) {
1049 plen = scsp_parse_ca(buff, len, &msg->sc_ca);
1051 case SCSP_CSU_REQ_MSG:
1052 case SCSP_CSU_REPLY_MSG:
1054 plen = scsp_parse_csu(buff, len, &msg->sc_csu_msg);
1056 case SCSP_HELLO_MSG:
1057 plen = scsp_parse_hello(buff, len, &msg->sc_hello);
1069 * Decode any extensions
1072 for (expp = &msg->sc_ext; len > 0;
1073 expp = &(*expp)->next) {
1074 plen = scsp_parse_ext(buff, len, expp);
1084 * Make sure we handled the whole message
1091 * Return the address of the SCSP message in internal format
1098 return(Scsp_msg *)0;