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.4 2003/11/15 20:33:43 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
86 * Read the long out of the input buffer
89 for (i = 0; i < sizeof(u_long); i++)
93 * Return the value in host order
100 * Free an SCSP Cache Alignment message in internal format
103 * cap pointer to CA message
110 scsp_free_ca(Scsp_ca *cap)
112 Scsp_csa *csap, *ncsap;
115 * Return if there's nothing to free
117 if (cap == (Scsp_ca *)0)
121 * Free the CSAS records
123 for (csap = cap->ca_csa_rec; csap; csap = ncsap) {
128 * Free the CA message structure
135 * Free an SCSP Cache State Update Request, Cache State Update Reply,
136 * or Cache State Update Solicit message in internal format
139 * csup pointer to CSU message
146 scsp_free_csu(Scsp_csu_msg *csup)
148 Scsp_csa *csap, *ncsap;
151 * Return if there's nothing to free
153 if (csup == (Scsp_csu_msg *)0)
157 * Free the CSA records
159 for (csap = csup->csu_csa_rec; csap; csap = ncsap) {
165 * Free the CSU message structure
172 * Free an SCSP Hello message in internal format
175 * hp pointer to Hello message
182 scsp_free_hello(Scsp_hello *hp)
185 * Return if there's nothing to free
187 if (hp == (Scsp_hello *)0)
191 * Free the Hello message structure
198 * Free an SCSP message in internal format
201 * msg pointer to input packet
208 scsp_free_msg(Scsp_msg *msg)
210 Scsp_ext *exp, *nexp;
213 * Return if there's nothing to free
215 if (msg == (Scsp_msg *)0)
219 * Free the message body
221 switch(msg->sc_msg_type) {
223 scsp_free_ca(msg->sc_ca);
225 case SCSP_CSU_REQ_MSG:
226 case SCSP_CSU_REPLY_MSG:
228 scsp_free_csu(msg->sc_csu_msg);
231 scsp_free_hello(msg->sc_hello);
236 * Free any extensions
238 for (exp = msg->sc_ext; exp; exp = nexp) {
244 * Free the message structure
251 * Parse a Sender or Receiver ID
255 * id_len length of ID
256 * idp pointer to structure to receive the ID
259 * 0 input was invalid
260 * else length of ID processed
264 scsp_parse_id(char *buff, int id_len, Scsp_id *idp)
270 id_len == 0 || id_len > SCSP_MAX_ID_LEN ||
278 idp->id_len = id_len;
283 UM_COPY(buff, idp->id, id_len);
286 * Return the ID length
293 * Parse the Mandatory Common Part of an SCSP input packet
296 * buff pointer to mandatory common part
297 * pdu_len length of input packet
298 * mcp pointer to location of MCP in decoded record
301 * 0 input was invalid
302 * else length of MCP in message
306 scsp_parse_mcp(char *buff, int pdu_len, Scsp_mcp *mcp)
310 struct scsp_nmcp *smp;
313 * Get the protocol ID
315 smp = (struct scsp_nmcp *)buff;
316 mcp->pid = ntohs(smp->sm_pid);
317 if (mcp->pid < SCSP_PROTO_ATMARP ||
318 mcp->pid > SCSP_PROTO_LNNI) {
319 /* Protocol ID is invalid */
324 * Get the server group ID
326 mcp->sgid = ntohs(smp->sm_sgid);
331 mcp->flags = ntohs(smp->sm_flags);
334 * Get the sender ID and length
336 idp = (u_char *) ((caddr_t)smp + sizeof(struct scsp_nmcp));
337 len = scsp_parse_id(idp, smp->sm_sid_len, &mcp->sid);
343 * Get the receiver ID and length
346 len = scsp_parse_id(idp, smp->sm_rid_len, &mcp->rid);
352 * Get the record count
354 mcp->rec_cnt = ntohs(smp->sm_rec_cnt);
357 * Return the length of data we processed
359 return(sizeof(struct scsp_nmcp) + smp->sm_sid_len +
371 * buff pointer to Extension
372 * pdu_len length of buffer
373 * expp pointer to location to receive pointer to the Extension
376 * 0 input was invalid
377 * else length of Extension processed
381 scsp_parse_ext(char *buff, int pdu_len, Scsp_ext **expp)
384 struct scsp_next *sep;
388 * Get memory for the extension
390 sep = (struct scsp_next *)buff;
391 len = sizeof(Scsp_ext) + ntohs(sep->se_len);
392 exp = (Scsp_ext *)UM_ALLOC(len);
401 exp->type = ntohs(sep->se_type);
406 exp->len = ntohs(sep->se_len);
412 UM_COPY((caddr_t)sep + sizeof(struct scsp_next),
413 (caddr_t)exp + sizeof(Scsp_ext),
418 * Save a pointer to the extension and return the
419 * number of bytes processed
422 return(sizeof(struct scsp_next) + exp->len);
433 * Parse a Cache State Advertisement or Cache State Advertisement
437 * buff pointer to CSA or CSAS record
438 * pdu_len length of input packet
439 * csapp pointer to location to put pointer to CSA or CSAS
442 * 0 input was invalid
443 * else length of record processed
447 scsp_parse_csa(char *buff, int pdu_len, Scsp_csa **csapp)
451 struct scsp_ncsa *scp;
452 Scsp_csa *csap = NULL;
455 * Check the record length
457 scp = (struct scsp_ncsa *)buff;
458 if (ntohs(scp->scs_len) < (sizeof(struct scsp_ncsa) +
459 scp->scs_ck_len + scp->scs_oid_len)) {
464 * Get memory for the returned structure
466 len = sizeof(Scsp_csa) + ntohs(scp->scs_len) -
467 sizeof(struct scsp_ncsa) - scp->scs_ck_len -
469 csap = (Scsp_csa *)UM_ALLOC(len);
478 csap->hops = ntohs(scp->scs_hop_cnt);
483 csap->null = (ntohs(scp->scs_nfill) & SCSP_CSAS_NULL) != 0;
486 * Get the sequence number
488 csap->seq = get_long((u_char *)&scp->scs_seq);
493 if (scp->scs_ck_len == 0 ||
494 scp->scs_ck_len > SCSP_MAX_KEY_LEN) {
497 csap->key.key_len = scp->scs_ck_len;
498 idp = (char *) ((caddr_t)scp + sizeof(struct scsp_ncsa));
499 UM_COPY(idp, csap->key.key, scp->scs_ck_len);
502 * Get the originator ID
504 idp += scp->scs_ck_len;
505 len = scsp_parse_id(idp, scp->scs_oid_len, &csap->oid);
511 * Get the protocol-specific data, if present
513 len = ntohs(scp->scs_len) - (sizeof(struct scsp_ncsa) +
514 scp->scs_ck_len + scp->scs_oid_len);
516 idp += scp->scs_oid_len;
517 len = scsp_parse_atmarp(idp, len, &csap->atmarp_data);
523 * Set a pointer to the MCP and return the length
524 * of data we processed
527 return(ntohs(scp->scs_len));
537 * Parse a Cache Alignment message
540 * buff pointer to start of CA in message
541 * pdu_len length of input packet
542 * capp pointer to location to put pointer to CA message
545 * 0 input was invalid
546 * else length of CA message processed
550 scsp_parse_ca(char *buff, int pdu_len, Scsp_ca **capp)
552 int i, len, proc_len;
553 struct scsp_nca *scap;
558 * Get memory for the returned structure
560 scap = (struct scsp_nca *)buff;
561 cap = (Scsp_ca *)UM_ALLOC(sizeof(Scsp_ca));
565 UM_ZERO(cap, sizeof(Scsp_ca));
568 * Get the sequence number
570 cap->ca_seq = get_long((u_char *)&scap->sca_seq);
571 proc_len = sizeof(scap->sca_seq);
572 buff += sizeof(scap->sca_seq);
575 * Process the mandatory common part of the message
577 len = scsp_parse_mcp(buff,
588 cap->ca_m = (cap->ca_mcp.flags & SCSP_CA_M) != 0;
589 cap->ca_i = (cap->ca_mcp.flags & SCSP_CA_I) != 0;
590 cap->ca_o = (cap->ca_mcp.flags & SCSP_CA_O) != 0;
593 * Get the CSAS records from the message
595 for (i = 0, csapp = &cap->ca_csa_rec; i < cap->ca_mcp.rec_cnt;
596 i++, csapp = &(*csapp)->next) {
597 len = scsp_parse_csa(buff, pdu_len - proc_len, csapp);
603 * Set the address of the CA message and
604 * return the length of processed data
617 * Parse the ATMARP-specific part of a CSA record
620 * buff pointer to ATMARP part of CSU message
621 * pdu_len length of data to process
622 * acspp pointer to location to put pointer to CSU message
625 * 0 input was invalid
626 * else length of CSU Req message processed
630 scsp_parse_atmarp(char *buff, int pdu_len, Scsp_atmarp_csa **acspp)
633 struct scsp_atmarp_ncsa *sacp;
634 Scsp_atmarp_csa *acsp = NULL;
637 * Initial packet verification
639 sacp = (struct scsp_atmarp_ncsa *)buff;
640 if ((sacp->sa_hrd != ntohs(ARP_ATMFORUM)) ||
641 (sacp->sa_pro != ntohs(ETHERTYPE_IP)))
645 * Get memory for the returned structure
647 acsp = (Scsp_atmarp_csa *)UM_ALLOC(sizeof(Scsp_atmarp_csa));
651 UM_ZERO(acsp, sizeof(Scsp_atmarp_csa));
656 acsp->sa_state = sacp->sa_state;
657 proc_len = sizeof(struct scsp_atmarp_ncsa);
660 * Verify/gather source ATM address
662 acsp->sa_sha.address_format = T_ATM_ABSENT;
663 acsp->sa_sha.address_length = 0;
664 if ((len = (sacp->sa_shtl & ARP_TL_LMASK)) != 0) {
665 if (sacp->sa_shtl & ARP_TL_E164) {
666 if (len > sizeof(Atm_addr_e164))
668 acsp->sa_sha.address_format = T_ATM_E164_ADDR;
670 if (len != sizeof(Atm_addr_nsap))
672 acsp->sa_sha.address_format = T_ATM_ENDSYS_ADDR;
674 acsp->sa_sha.address_length = len;
675 if (pdu_len < proc_len + len)
677 UM_COPY(&buff[proc_len], (char *)acsp->sa_sha.address,
683 * Verify/gather source ATM subaddress
685 acsp->sa_ssa.address_format = T_ATM_ABSENT;
686 acsp->sa_ssa.address_length = 0;
687 if ((len = (sacp->sa_sstl & ARP_TL_LMASK)) != 0) {
688 if (((sacp->sa_sstl & ARP_TL_TMASK) != ARP_TL_NSAPA) ||
689 (len != sizeof(Atm_addr_nsap)))
691 acsp->sa_ssa.address_format = T_ATM_ENDSYS_ADDR;
692 acsp->sa_ssa.address_length = len;
693 if (pdu_len < proc_len + len)
695 UM_COPY(&buff[proc_len], (char *)acsp->sa_ssa.address,
701 * Verify/gather source IP address
703 if ((len = sacp->sa_spln) != 0) {
704 if (len != sizeof(struct in_addr))
706 if (pdu_len < proc_len + len)
708 UM_COPY(&buff[proc_len], (char *)&acsp->sa_spa, len);
711 acsp->sa_spa.s_addr = 0;
715 * Verify/gather target ATM address
717 acsp->sa_tha.address_format = T_ATM_ABSENT;
718 acsp->sa_tha.address_length = 0;
719 if ((len = (sacp->sa_thtl & ARP_TL_LMASK)) != 0) {
720 if (sacp->sa_thtl & ARP_TL_E164) {
721 if (len > sizeof(Atm_addr_e164))
723 acsp->sa_tha.address_format = T_ATM_E164_ADDR;
725 if (len != sizeof(Atm_addr_nsap))
727 acsp->sa_tha.address_format = T_ATM_ENDSYS_ADDR;
729 acsp->sa_tha.address_length = len;
730 if (pdu_len < proc_len + len)
732 UM_COPY(&buff[proc_len], (char *)acsp->sa_tha.address,
738 * Verify/gather target ATM subaddress
740 acsp->sa_tsa.address_format = T_ATM_ABSENT;
741 acsp->sa_tsa.address_length = 0;
742 if ((len = (sacp->sa_tstl & ARP_TL_LMASK)) != 0) {
743 if (((sacp->sa_tstl & ARP_TL_TMASK) != ARP_TL_NSAPA) ||
744 (len != sizeof(Atm_addr_nsap)))
746 acsp->sa_tsa.address_format = T_ATM_ENDSYS_ADDR;
747 acsp->sa_tsa.address_length = len;
748 if (pdu_len < proc_len + len)
750 UM_COPY(&buff[proc_len], (char *)acsp->sa_tsa.address,
756 * Verify/gather target IP address
758 if ((len = sacp->sa_tpln) != 0) {
759 if (len != sizeof(struct in_addr))
761 if (pdu_len < proc_len + len)
763 UM_COPY(&buff[proc_len], (char *)&acsp->sa_tpa, len);
766 acsp->sa_tpa.s_addr = 0;
770 * Verify packet length
772 if (proc_len != pdu_len)
786 * Parse a Cache State Update Request, Cache State Update Reply, or
787 * Cache State Update Solicit message. These all have the same format,
788 * a Mandatory Common Part followed by a number of CSA or CSAS records.
791 * buff pointer to start of CSU message
792 * pdu_len length of input packet
793 * csupp pointer to location to put pointer to CSU message
796 * 0 input was invalid
797 * else length of CSU Req message processed
801 scsp_parse_csu(char *buff, int pdu_len, Scsp_csu_msg **csupp)
803 int i, len, proc_len;
808 * Get memory for the returned structure
810 csup = (Scsp_csu_msg *)UM_ALLOC(sizeof(Scsp_csu_msg));
814 UM_ZERO(csup, sizeof(Scsp_csu_msg));
817 * Process the mandatory common part of the message
819 len = scsp_parse_mcp(buff, pdu_len, &csup->csu_mcp);
826 * Get the CSAS records from the message
828 for (i = 0, csapp = &csup->csu_csa_rec;
829 i < csup->csu_mcp.rec_cnt;
830 i++, csapp = &(*csapp)->next) {
831 len = scsp_parse_csa(buff, pdu_len - proc_len, csapp);
837 * Set the address of the CSU Req message and
838 * return the length of processed data
851 * Parse a Hello message
854 * buff pointer to start of Hello in message
855 * pdu_len length of input packet
856 * hpp pointer to location to put pointer to Hello message
859 * 0 input was invalid
860 * else length of Hello message processed
864 scsp_parse_hello(char *buff, int pdu_len, Scsp_hello **hpp)
866 int i, len, proc_len;
867 struct scsp_nhello *shp = (struct scsp_nhello *)buff;
873 * Get memory for the returned structure
875 hp = (Scsp_hello *)UM_ALLOC(sizeof(Scsp_hello));
879 UM_ZERO(hp, sizeof(Scsp_hello));
882 * Get the hello interval
884 hp->hello_int = ntohs(shp->sch_hi);
887 * Get the dead factor
889 hp->dead_factor = ntohs(shp->sch_df);
894 hp->family_id = ntohs(shp->sch_fid);
897 * Process the mandatory common part of the message
899 proc_len = sizeof(struct scsp_nhello) -
900 sizeof(struct scsp_nmcp);
902 len = scsp_parse_mcp(buff, pdu_len - proc_len,
910 * Get additional receiver ID records from the message
912 for (i = 0, ridpp = &hp->hello_mcp.rid.next;
913 i < hp->hello_mcp.rec_cnt;
914 i++, ridpp = &idp->next) {
915 idp = (Scsp_id *)UM_ALLOC(sizeof(Scsp_id));
919 UM_ZERO(idp, sizeof(Scsp_id));
920 len = scsp_parse_id(buff,
921 hp->hello_mcp.rid.id_len,
933 * Set the address of the CA message and
934 * return the length of processed data
947 * Parse an SCSP input packet
950 * buff pointer to input packet
951 * pdu_len length of input packet
954 * NULL input packet was invalid
955 * else pointer to packet in internal format
959 scsp_parse_msg(char *buff, int pdu_len)
961 int ext_off, len, plen;
962 struct scsp_nhdr *shp;
963 Scsp_msg *msg = (Scsp_msg *)0;
967 * Check the message checksum
969 if (ip_checksum(buff, pdu_len) != 0) {
971 * Checksum was bad--discard the message
977 * Allocate storage for the message
979 msg = (Scsp_msg *)UM_ALLOC(sizeof(Scsp_msg));
983 UM_ZERO(msg, sizeof(Scsp_msg));
986 * Decode the fixed header
990 shp = (struct scsp_nhdr *)buff;
991 if (shp->sh_ver != SCSP_VER_1)
995 * Get the message type
997 msg->sc_msg_type = shp->sh_type;
1000 * Get and check the length
1002 len = ntohs(shp->sh_len);
1007 * Get the extension offset
1009 ext_off = ntohs(shp->sh_ext_off);
1012 * Decode the body of the message, depending on the type
1014 buff += sizeof(struct scsp_nhdr);
1015 len -= sizeof(struct scsp_nhdr);
1016 switch(msg->sc_msg_type) {
1018 plen = scsp_parse_ca(buff, len, &msg->sc_ca);
1020 case SCSP_CSU_REQ_MSG:
1021 case SCSP_CSU_REPLY_MSG:
1023 plen = scsp_parse_csu(buff, len, &msg->sc_csu_msg);
1025 case SCSP_HELLO_MSG:
1026 plen = scsp_parse_hello(buff, len, &msg->sc_hello);
1038 * Decode any extensions
1041 for (expp = &msg->sc_ext; len > 0;
1042 expp = &(*expp)->next) {
1043 plen = scsp_parse_ext(buff, len, expp);
1053 * Make sure we handled the whole message
1060 * Return the address of the SCSP message in internal format
1067 return(Scsp_msg *)0;