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.
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>
64 __RCSID("@(#) $FreeBSD$");
68 static int scsp_parse_atmarp(char *, int, Scsp_atmarp_csa **);
74 * This routine is provided to handle long integers that may not
75 * be word-aligned in the input buffer.
78 * cp pointer to long int in message
81 * int long int in host order
92 * Read the long out of the input buffer
95 for (i = 0; i < sizeof(u_long); i++)
99 * Return the value in host order
106 * Free an SCSP Cache Alignment message in internal format
109 * cap pointer to CA message
119 Scsp_csa *csap, *ncsap;
122 * Return if there's nothing to free
124 if (cap == (Scsp_ca *)0)
128 * Free the CSAS records
130 for (csap = cap->ca_csa_rec; csap; csap = ncsap) {
135 * Free the CA message structure
142 * Free an SCSP Cache State Update Request, Cache State Update Reply,
143 * or Cache State Update Solicit message in internal format
146 * csup pointer to CSU message
156 Scsp_csa *csap, *ncsap;
159 * Return if there's nothing to free
161 if (csup == (Scsp_csu_msg *)0)
165 * Free the CSA records
167 for (csap = csup->csu_csa_rec; csap; csap = ncsap) {
173 * Free the CSU message structure
180 * Free an SCSP Hello message in internal format
183 * hp pointer to Hello message
194 * Return if there's nothing to free
196 if (hp == (Scsp_hello *)0)
200 * Free the Hello message structure
207 * Free an SCSP message in internal format
210 * msg pointer to input packet
220 Scsp_ext *exp, *nexp;
223 * Return if there's nothing to free
225 if (msg == (Scsp_msg *)0)
229 * Free the message body
231 switch(msg->sc_msg_type) {
233 scsp_free_ca(msg->sc_ca);
235 case SCSP_CSU_REQ_MSG:
236 case SCSP_CSU_REPLY_MSG:
238 scsp_free_csu(msg->sc_csu_msg);
241 scsp_free_hello(msg->sc_hello);
246 * Free any extensions
248 for (exp = msg->sc_ext; exp; exp = nexp) {
254 * Free the message structure
261 * Parse a Sender or Receiver ID
265 * id_len length of ID
266 * idp pointer to structure to receive the ID
269 * 0 input was invalid
270 * else length of ID processed
274 scsp_parse_id(buff, id_len, idp)
283 id_len == 0 || id_len > SCSP_MAX_ID_LEN ||
291 idp->id_len = id_len;
296 bcopy(buff, idp->id, id_len);
299 * Return the ID length
306 * Parse the Mandatory Common Part of an SCSP input packet
309 * buff pointer to mandatory common part
310 * pdu_len length of input packet
311 * mcp pointer to location of MCP in decoded record
314 * 0 input was invalid
315 * else length of MCP in message
319 scsp_parse_mcp(buff, pdu_len, mcp)
326 struct scsp_nmcp *smp;
329 * Get the protocol ID
331 smp = (struct scsp_nmcp *)buff;
332 mcp->pid = ntohs(smp->sm_pid);
333 if (mcp->pid < SCSP_PROTO_ATMARP ||
334 mcp->pid > SCSP_PROTO_LNNI) {
335 /* Protocol ID is invalid */
340 * Get the server group ID
342 mcp->sgid = ntohs(smp->sm_sgid);
347 mcp->flags = ntohs(smp->sm_flags);
350 * Get the sender ID and length
352 idp = (u_char *) ((caddr_t)smp + sizeof(struct scsp_nmcp));
353 len = scsp_parse_id(idp, smp->sm_sid_len, &mcp->sid);
359 * Get the receiver ID and length
362 len = scsp_parse_id(idp, smp->sm_rid_len, &mcp->rid);
368 * Get the record count
370 mcp->rec_cnt = ntohs(smp->sm_rec_cnt);
373 * Return the length of data we processed
375 return(sizeof(struct scsp_nmcp) + smp->sm_sid_len +
387 * buff pointer to Extension
388 * pdu_len length of buffer
389 * expp pointer to location to receive pointer to the Extension
392 * 0 input was invalid
393 * else length of Extension processed
397 scsp_parse_ext(buff, pdu_len, expp)
403 struct scsp_next *sep;
407 * Get memory for the extension
409 sep = (struct scsp_next *)buff;
410 len = sizeof(Scsp_ext) + ntohs(sep->se_len);
411 exp = calloc(1, len);
418 exp->type = ntohs(sep->se_type);
423 exp->len = ntohs(sep->se_len);
429 bcopy((caddr_t)sep + sizeof(struct scsp_next),
430 (caddr_t)exp + sizeof(Scsp_ext),
435 * Save a pointer to the extension and return the
436 * number of bytes processed
439 return(sizeof(struct scsp_next) + exp->len);
450 * Parse a Cache State Advertisement or Cache State Advertisement
454 * buff pointer to CSA or CSAS record
455 * pdu_len length of input packet
456 * csapp pointer to location to put pointer to CSA or CSAS
459 * 0 input was invalid
460 * else length of record processed
464 scsp_parse_csa(buff, pdu_len, csapp)
471 struct scsp_ncsa *scp;
472 Scsp_csa *csap = NULL;
475 * Check the record length
477 scp = (struct scsp_ncsa *)buff;
478 if (ntohs(scp->scs_len) < (sizeof(struct scsp_ncsa) +
479 scp->scs_ck_len + scp->scs_oid_len)) {
484 * Get memory for the returned structure
486 len = sizeof(Scsp_csa) + ntohs(scp->scs_len) -
487 sizeof(struct scsp_ncsa) - scp->scs_ck_len -
489 csap = calloc(1, len);
496 csap->hops = ntohs(scp->scs_hop_cnt);
501 csap->null = (ntohs(scp->scs_nfill) & SCSP_CSAS_NULL) != 0;
504 * Get the sequence number
506 csap->seq = get_long((u_char *)&scp->scs_seq);
511 if (scp->scs_ck_len == 0 ||
512 scp->scs_ck_len > SCSP_MAX_KEY_LEN) {
515 csap->key.key_len = scp->scs_ck_len;
516 idp = (char *) ((caddr_t)scp + sizeof(struct scsp_ncsa));
517 bcopy(idp, csap->key.key, scp->scs_ck_len);
520 * Get the originator ID
522 idp += scp->scs_ck_len;
523 len = scsp_parse_id(idp, scp->scs_oid_len, &csap->oid);
529 * Get the protocol-specific data, if present
531 len = ntohs(scp->scs_len) - (sizeof(struct scsp_ncsa) +
532 scp->scs_ck_len + scp->scs_oid_len);
534 idp += scp->scs_oid_len;
535 len = scsp_parse_atmarp(idp, len, &csap->atmarp_data);
541 * Set a pointer to the MCP and return the length
542 * of data we processed
545 return(ntohs(scp->scs_len));
555 * Parse a Cache Alignment message
558 * buff pointer to start of CA in message
559 * pdu_len length of input packet
560 * capp pointer to location to put pointer to CA message
563 * 0 input was invalid
564 * else length of CA message processed
568 scsp_parse_ca(buff, pdu_len, capp)
573 int i, len, proc_len;
574 struct scsp_nca *scap;
579 * Get memory for the returned structure
581 scap = (struct scsp_nca *)buff;
582 cap = calloc(1, sizeof(Scsp_ca));
587 * Get the sequence number
589 cap->ca_seq = get_long((u_char *)&scap->sca_seq);
590 proc_len = sizeof(scap->sca_seq);
591 buff += sizeof(scap->sca_seq);
594 * Process the mandatory common part of the message
596 len = scsp_parse_mcp(buff,
607 cap->ca_m = (cap->ca_mcp.flags & SCSP_CA_M) != 0;
608 cap->ca_i = (cap->ca_mcp.flags & SCSP_CA_I) != 0;
609 cap->ca_o = (cap->ca_mcp.flags & SCSP_CA_O) != 0;
612 * Get the CSAS records from the message
614 for (i = 0, csapp = &cap->ca_csa_rec; i < cap->ca_mcp.rec_cnt;
615 i++, csapp = &(*csapp)->next) {
616 len = scsp_parse_csa(buff, pdu_len - proc_len, csapp);
622 * Set the address of the CA message and
623 * return the length of processed data
636 * Parse the ATMARP-specific part of a CSA record
639 * buff pointer to ATMARP part of CSU message
640 * pdu_len length of data to process
641 * acspp pointer to location to put pointer to CSU message
644 * 0 input was invalid
645 * else length of CSU Req message processed
649 scsp_parse_atmarp(buff, pdu_len, acspp)
652 Scsp_atmarp_csa **acspp;
655 struct scsp_atmarp_ncsa *sacp;
656 Scsp_atmarp_csa *acsp = NULL;
659 * Initial packet verification
661 sacp = (struct scsp_atmarp_ncsa *)buff;
662 if ((sacp->sa_hrd != ntohs(ARP_ATMFORUM)) ||
663 (sacp->sa_pro != ntohs(ETHERTYPE_IP)))
667 * Get memory for the returned structure
669 acsp = calloc(1, sizeof(Scsp_atmarp_csa));
676 acsp->sa_state = sacp->sa_state;
677 proc_len = sizeof(struct scsp_atmarp_ncsa);
680 * Verify/gather source ATM address
682 acsp->sa_sha.address_format = T_ATM_ABSENT;
683 acsp->sa_sha.address_length = 0;
684 if ((len = (sacp->sa_shtl & ARP_TL_LMASK)) != 0) {
685 if (sacp->sa_shtl & ARP_TL_E164) {
686 if (len > sizeof(Atm_addr_e164))
688 acsp->sa_sha.address_format = T_ATM_E164_ADDR;
690 if (len != sizeof(Atm_addr_nsap))
692 acsp->sa_sha.address_format = T_ATM_ENDSYS_ADDR;
694 acsp->sa_sha.address_length = len;
695 if (pdu_len < proc_len + len)
697 bcopy(&buff[proc_len], (char *)acsp->sa_sha.address,
703 * Verify/gather source ATM subaddress
705 acsp->sa_ssa.address_format = T_ATM_ABSENT;
706 acsp->sa_ssa.address_length = 0;
707 if ((len = (sacp->sa_sstl & ARP_TL_LMASK)) != 0) {
708 if (((sacp->sa_sstl & ARP_TL_TMASK) != ARP_TL_NSAPA) ||
709 (len != sizeof(Atm_addr_nsap)))
711 acsp->sa_ssa.address_format = T_ATM_ENDSYS_ADDR;
712 acsp->sa_ssa.address_length = len;
713 if (pdu_len < proc_len + len)
715 bcopy(&buff[proc_len], (char *)acsp->sa_ssa.address,
721 * Verify/gather source IP address
723 if ((len = sacp->sa_spln) != 0) {
724 if (len != sizeof(struct in_addr))
726 if (pdu_len < proc_len + len)
728 bcopy(&buff[proc_len], (char *)&acsp->sa_spa, len);
731 acsp->sa_spa.s_addr = 0;
735 * Verify/gather target ATM address
737 acsp->sa_tha.address_format = T_ATM_ABSENT;
738 acsp->sa_tha.address_length = 0;
739 if ((len = (sacp->sa_thtl & ARP_TL_LMASK)) != 0) {
740 if (sacp->sa_thtl & ARP_TL_E164) {
741 if (len > sizeof(Atm_addr_e164))
743 acsp->sa_tha.address_format = T_ATM_E164_ADDR;
745 if (len != sizeof(Atm_addr_nsap))
747 acsp->sa_tha.address_format = T_ATM_ENDSYS_ADDR;
749 acsp->sa_tha.address_length = len;
750 if (pdu_len < proc_len + len)
752 bcopy(&buff[proc_len], (char *)acsp->sa_tha.address,
758 * Verify/gather target ATM subaddress
760 acsp->sa_tsa.address_format = T_ATM_ABSENT;
761 acsp->sa_tsa.address_length = 0;
762 if ((len = (sacp->sa_tstl & ARP_TL_LMASK)) != 0) {
763 if (((sacp->sa_tstl & ARP_TL_TMASK) != ARP_TL_NSAPA) ||
764 (len != sizeof(Atm_addr_nsap)))
766 acsp->sa_tsa.address_format = T_ATM_ENDSYS_ADDR;
767 acsp->sa_tsa.address_length = len;
768 if (pdu_len < proc_len + len)
770 bcopy(&buff[proc_len], (char *)acsp->sa_tsa.address,
776 * Verify/gather target IP address
778 if ((len = sacp->sa_tpln) != 0) {
779 if (len != sizeof(struct in_addr))
781 if (pdu_len < proc_len + len)
783 bcopy(&buff[proc_len], (char *)&acsp->sa_tpa, len);
786 acsp->sa_tpa.s_addr = 0;
790 * Verify packet length
792 if (proc_len != pdu_len)
806 * Parse a Cache State Update Request, Cache State Update Reply, or
807 * Cache State Update Solicit message. These all have the same format,
808 * a Mandatory Common Part followed by a number of CSA or CSAS records.
811 * buff pointer to start of CSU message
812 * pdu_len length of input packet
813 * csupp pointer to location to put pointer to CSU message
816 * 0 input was invalid
817 * else length of CSU Req message processed
821 scsp_parse_csu(buff, pdu_len, csupp)
824 Scsp_csu_msg **csupp;
826 int i, len, proc_len;
831 * Get memory for the returned structure
833 csup = calloc(1, sizeof(Scsp_csu_msg));
838 * Process the mandatory common part of the message
840 len = scsp_parse_mcp(buff, pdu_len, &csup->csu_mcp);
847 * Get the CSAS records from the message
849 for (i = 0, csapp = &csup->csu_csa_rec;
850 i < csup->csu_mcp.rec_cnt;
851 i++, csapp = &(*csapp)->next) {
852 len = scsp_parse_csa(buff, pdu_len - proc_len, csapp);
858 * Set the address of the CSU Req message and
859 * return the length of processed data
872 * Parse a Hello message
875 * buff pointer to start of Hello in message
876 * pdu_len length of input packet
877 * hpp pointer to location to put pointer to Hello message
880 * 0 input was invalid
881 * else length of Hello message processed
885 scsp_parse_hello(buff, pdu_len, hpp)
890 int i, len, proc_len;
891 struct scsp_nhello *shp = (struct scsp_nhello *)buff;
897 * Get memory for the returned structure
899 hp = calloc(1, sizeof(Scsp_hello));
904 * Get the hello interval
906 hp->hello_int = ntohs(shp->sch_hi);
909 * Get the dead factor
911 hp->dead_factor = ntohs(shp->sch_df);
916 hp->family_id = ntohs(shp->sch_fid);
919 * Process the mandatory common part of the message
921 proc_len = sizeof(struct scsp_nhello) -
922 sizeof(struct scsp_nmcp);
924 len = scsp_parse_mcp(buff, pdu_len - proc_len,
932 * Get additional receiver ID records from the message
934 for (i = 0, ridpp = &hp->hello_mcp.rid.next;
935 i < hp->hello_mcp.rec_cnt;
936 i++, ridpp = &idp->next) {
937 idp = calloc(1, sizeof(Scsp_id));
940 len = scsp_parse_id(buff,
941 hp->hello_mcp.rid.id_len,
953 * Set the address of the CA message and
954 * return the length of processed data
967 * Parse an SCSP input packet
970 * buff pointer to input packet
971 * pdu_len length of input packet
974 * NULL input packet was invalid
975 * else pointer to packet in internal format
979 scsp_parse_msg(buff, pdu_len)
983 int ext_off, len, plen;
984 struct scsp_nhdr *shp;
985 Scsp_msg *msg = (Scsp_msg *)0;
989 * Check the message checksum
991 if (ip_checksum(buff, pdu_len) != 0) {
993 * Checksum was bad--discard the message
999 * Allocate storage for the message
1001 msg = calloc(1, sizeof(Scsp_msg));
1006 * Decode the fixed header
1010 shp = (struct scsp_nhdr *)buff;
1011 if (shp->sh_ver != SCSP_VER_1)
1015 * Get the message type
1017 msg->sc_msg_type = shp->sh_type;
1020 * Get and check the length
1022 len = ntohs(shp->sh_len);
1027 * Get the extension offset
1029 ext_off = ntohs(shp->sh_ext_off);
1032 * Decode the body of the message, depending on the type
1034 buff += sizeof(struct scsp_nhdr);
1035 len -= sizeof(struct scsp_nhdr);
1036 switch(msg->sc_msg_type) {
1038 plen = scsp_parse_ca(buff, len, &msg->sc_ca);
1040 case SCSP_CSU_REQ_MSG:
1041 case SCSP_CSU_REPLY_MSG:
1043 plen = scsp_parse_csu(buff, len, &msg->sc_csu_msg);
1045 case SCSP_HELLO_MSG:
1046 plen = scsp_parse_hello(buff, len, &msg->sc_hello);
1058 * Decode any extensions
1061 for (expp = &msg->sc_ext; len > 0;
1062 expp = &(*expp)->next) {
1063 plen = scsp_parse_ext(buff, len, expp);
1073 * Make sure we handled the whole message
1080 * Return the address of the SCSP message in internal format
1087 return(Scsp_msg *)0;