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
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
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
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
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
= NULL
;
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