kernel - VM PAGER part 1/2 - Remove vm_page_alloc()
[dragonfly.git] / usr.sbin / atm / scspd / scsp_input.c
blob763717ad6188cff9679de7df285ec74af2ad8319
1 /*
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>
42 #include <net/if.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>
52 #include <errno.h>
53 #include <libatm.h>
54 #include <stdio.h>
55 #include <stdlib.h>
56 #include <string.h>
57 #include <syslog.h>
59 #include "scsp_msg.h"
60 #include "scsp_if.h"
61 #include "scsp_var.h"
63 static int scsp_parse_atmarp(char *, int, Scsp_atmarp_csa **);
67 * Get a long ingeter
69 * This routine is provided to handle long integers that may not
70 * be word-aligned in the input buffer.
72 * Arguments:
73 * cp pointer to long int in message
75 * Returns:
76 * int long int in host order
79 static u_long
80 get_long(u_char *cp)
82 int i;
83 u_long l;
86 * Read the long out of the input buffer
88 l = 0;
89 for (i = 0; i < sizeof(u_long); i++)
90 l = (l << 8) + *cp++;
93 * Return the value in host order
95 return(l);
100 * Free an SCSP Cache Alignment message in internal format
102 * Arguments:
103 * cap pointer to CA message
105 * Returns:
106 * None
109 static void
110 scsp_free_ca(Scsp_ca *cap)
112 Scsp_csa *csap, *ncsap;
115 * Return if there's nothing to free
117 if (cap == NULL)
118 return;
121 * Free the CSAS records
123 for (csap = cap->ca_csa_rec; csap; csap = ncsap) {
124 ncsap = csap->next;
125 SCSP_FREE_CSA(csap);
128 * Free the CA message structure
130 UM_FREE(cap);
135 * Free an SCSP Cache State Update Request, Cache State Update Reply,
136 * or Cache State Update Solicit message in internal format
138 * Arguments:
139 * csup pointer to CSU message
141 * Returns:
142 * None
145 static void
146 scsp_free_csu(Scsp_csu_msg *csup)
148 Scsp_csa *csap, *ncsap;
151 * Return if there's nothing to free
153 if (csup == NULL)
154 return;
157 * Free the CSA records
159 for (csap = csup->csu_csa_rec; csap; csap = ncsap) {
160 ncsap = csap->next;
161 SCSP_FREE_CSA(csap);
165 * Free the CSU message structure
167 UM_FREE(csup);
172 * Free an SCSP Hello message in internal format
174 * Arguments:
175 * hp pointer to Hello message
177 * Returns:
178 * None
181 static void
182 scsp_free_hello(Scsp_hello *hp)
185 * Return if there's nothing to free
187 if (hp == NULL)
188 return;
191 * Free the Hello message structure
193 UM_FREE(hp);
198 * Free an SCSP message in internal format
200 * Arguments:
201 * msg pointer to input packet
203 * Returns:
204 * None
207 void
208 scsp_free_msg(Scsp_msg *msg)
210 Scsp_ext *exp, *nexp;
213 * Return if there's nothing to free
215 if (msg == NULL)
216 return;
219 * Free the message body
221 switch(msg->sc_msg_type) {
222 case SCSP_CA_MSG:
223 scsp_free_ca(msg->sc_ca);
224 break;
225 case SCSP_CSU_REQ_MSG:
226 case SCSP_CSU_REPLY_MSG:
227 case SCSP_CSUS_MSG:
228 scsp_free_csu(msg->sc_csu_msg);
229 break;
230 case SCSP_HELLO_MSG:
231 scsp_free_hello(msg->sc_hello);
232 break;
236 * Free any extensions
238 for (exp = msg->sc_ext; exp; exp = nexp) {
239 nexp = exp->next;
240 UM_FREE(exp);
244 * Free the message structure
246 UM_FREE(msg);
251 * Parse a Sender or Receiver ID
253 * Arguments:
254 * buff pointer to ID
255 * id_len length of ID
256 * idp pointer to structure to receive the ID
258 * Returns:
259 * 0 input was invalid
260 * else length of ID processed
263 static int
264 scsp_parse_id(char *buff, int id_len, Scsp_id *idp)
267 * Sanity check
269 if (!buff ||
270 id_len == 0 || id_len > SCSP_MAX_ID_LEN ||
271 !idp) {
272 return(0);
276 * Save the ID length
278 idp->id_len = id_len;
281 * Get the ID
283 UM_COPY(buff, idp->id, id_len);
286 * Return the ID length
288 return(id_len);
293 * Parse the Mandatory Common Part of an SCSP input packet
295 * Arguments:
296 * buff pointer to mandatory common part
297 * pdu_len length of input packet
298 * mcp pointer to location of MCP in decoded record
300 * Returns:
301 * 0 input was invalid
302 * else length of MCP in message
305 static int
306 scsp_parse_mcp(char *buff, int pdu_len, Scsp_mcp *mcp)
308 int len;
309 u_char *idp;
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 */
320 goto mcp_invalid;
324 * Get the server group ID
326 mcp->sgid = ntohs(smp->sm_sgid);
329 * Get the flags
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);
338 if (len == 0) {
339 goto mcp_invalid;
343 * Get the receiver ID and length
345 idp += len;
346 len = scsp_parse_id(idp, smp->sm_rid_len, &mcp->rid);
347 if (len == 0) {
348 goto mcp_invalid;
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 +
360 smp->sm_rid_len);
362 mcp_invalid:
363 return(0);
368 * Parse an Extension
370 * Arguments:
371 * buff pointer to Extension
372 * pdu_len length of buffer
373 * expp pointer to location to receive pointer to the Extension
375 * Returns:
376 * 0 input was invalid
377 * else length of Extension processed
380 static int
381 scsp_parse_ext(char *buff, int pdu_len, Scsp_ext **expp)
383 int len;
384 struct scsp_next *sep;
385 Scsp_ext *exp;
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);
393 if (!exp) {
394 goto ext_invalid;
396 UM_ZERO(exp, len);
399 * Get the type
401 exp->type = ntohs(sep->se_type);
404 * Get the length
406 exp->len = ntohs(sep->se_len);
409 * Get the value
411 if (exp->len > 0) {
412 UM_COPY((caddr_t)sep + sizeof(struct scsp_next),
413 (caddr_t)exp + sizeof(Scsp_ext),
414 exp->len);
418 * Save a pointer to the extension and return the
419 * number of bytes processed
421 *expp = exp;
422 return(sizeof(struct scsp_next) + exp->len);
424 ext_invalid:
425 if (exp) {
426 UM_FREE(exp);
428 return(0);
433 * Parse a Cache State Advertisement or Cache State Advertisement
434 * Summary record
436 * Arguments:
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
441 * Returns:
442 * 0 input was invalid
443 * else length of record processed
446 static int
447 scsp_parse_csa(char *buff, int pdu_len, Scsp_csa **csapp)
449 int len;
450 char *idp;
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)) {
460 goto csa_invalid;
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 -
468 scp->scs_oid_len;
469 csap = (Scsp_csa *)UM_ALLOC(len);
470 if (!csap) {
471 goto csa_invalid;
473 UM_ZERO(csap, len);
476 * Get the hop count
478 csap->hops = ntohs(scp->scs_hop_cnt);
481 * Set the null flag
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);
491 * Get the cache key
493 if (scp->scs_ck_len == 0 ||
494 scp->scs_ck_len > SCSP_MAX_KEY_LEN) {
495 goto csa_invalid;
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);
506 if (len == 0) {
507 goto csa_invalid;
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);
515 if (len > 0) {
516 idp += scp->scs_oid_len;
517 len = scsp_parse_atmarp(idp, len, &csap->atmarp_data);
518 if (len == 0)
519 goto csa_invalid;
523 * Set a pointer to the MCP and return the length
524 * of data we processed
526 *csapp = csap;
527 return(ntohs(scp->scs_len));
529 csa_invalid:
530 if (csap)
531 SCSP_FREE_CSA(csap);
532 return(0);
537 * Parse a Cache Alignment message
539 * Arguments:
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
544 * Returns:
545 * 0 input was invalid
546 * else length of CA message processed
549 static int
550 scsp_parse_ca(char *buff, int pdu_len, Scsp_ca **capp)
552 int i, len, proc_len;
553 struct scsp_nca *scap;
554 Scsp_ca *cap;
555 Scsp_csa **csapp;
558 * Get memory for the returned structure
560 scap = (struct scsp_nca *)buff;
561 cap = (Scsp_ca *)UM_ALLOC(sizeof(Scsp_ca));
562 if (!cap) {
563 goto ca_invalid;
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,
578 pdu_len - proc_len,
579 &cap->ca_mcp);
580 if (len == 0)
581 goto ca_invalid;
582 buff += len;
583 proc_len += len;
586 * Set the flags
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);
598 buff += len;
599 proc_len += len;
603 * Set the address of the CA message and
604 * return the length of processed data
606 *capp = cap;
607 return(proc_len);
609 ca_invalid:
610 if (cap)
611 scsp_free_ca(cap);
612 return(0);
617 * Parse the ATMARP-specific part of a CSA record
619 * Arguments:
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
624 * Returns:
625 * 0 input was invalid
626 * else length of CSU Req message processed
629 static int
630 scsp_parse_atmarp(char *buff, int pdu_len, Scsp_atmarp_csa **acspp)
632 int len, proc_len;
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)))
642 goto acs_invalid;
645 * Get memory for the returned structure
647 acsp = (Scsp_atmarp_csa *)UM_ALLOC(sizeof(Scsp_atmarp_csa));
648 if (!acsp) {
649 goto acs_invalid;
651 UM_ZERO(acsp, sizeof(Scsp_atmarp_csa));
654 * Get state code
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))
667 goto acs_invalid;
668 acsp->sa_sha.address_format = T_ATM_E164_ADDR;
669 } else {
670 if (len != sizeof(Atm_addr_nsap))
671 goto acs_invalid;
672 acsp->sa_sha.address_format = T_ATM_ENDSYS_ADDR;
674 acsp->sa_sha.address_length = len;
675 if (pdu_len < proc_len + len)
676 goto acs_invalid;
677 UM_COPY(&buff[proc_len], (char *)acsp->sa_sha.address,
678 len);
679 proc_len += len;
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)))
690 goto acs_invalid;
691 acsp->sa_ssa.address_format = T_ATM_ENDSYS_ADDR;
692 acsp->sa_ssa.address_length = len;
693 if (pdu_len < proc_len + len)
694 goto acs_invalid;
695 UM_COPY(&buff[proc_len], (char *)acsp->sa_ssa.address,
696 len);
697 proc_len += len;
701 * Verify/gather source IP address
703 if ((len = sacp->sa_spln) != 0) {
704 if (len != sizeof(struct in_addr))
705 goto acs_invalid;
706 if (pdu_len < proc_len + len)
707 goto acs_invalid;
708 UM_COPY(&buff[proc_len], (char *)&acsp->sa_spa, len);
709 proc_len += len;
710 } else {
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))
722 goto acs_invalid;
723 acsp->sa_tha.address_format = T_ATM_E164_ADDR;
724 } else {
725 if (len != sizeof(Atm_addr_nsap))
726 goto acs_invalid;
727 acsp->sa_tha.address_format = T_ATM_ENDSYS_ADDR;
729 acsp->sa_tha.address_length = len;
730 if (pdu_len < proc_len + len)
731 goto acs_invalid;
732 UM_COPY(&buff[proc_len], (char *)acsp->sa_tha.address,
733 len);
734 proc_len += len;
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)))
745 goto acs_invalid;
746 acsp->sa_tsa.address_format = T_ATM_ENDSYS_ADDR;
747 acsp->sa_tsa.address_length = len;
748 if (pdu_len < proc_len + len)
749 goto acs_invalid;
750 UM_COPY(&buff[proc_len], (char *)acsp->sa_tsa.address,
751 len);
752 proc_len += len;
756 * Verify/gather target IP address
758 if ((len = sacp->sa_tpln) != 0) {
759 if (len != sizeof(struct in_addr))
760 goto acs_invalid;
761 if (pdu_len < proc_len + len)
762 goto acs_invalid;
763 UM_COPY(&buff[proc_len], (char *)&acsp->sa_tpa, len);
764 proc_len += len;
765 } else {
766 acsp->sa_tpa.s_addr = 0;
770 * Verify packet length
772 if (proc_len != pdu_len)
773 goto acs_invalid;
775 *acspp = acsp;
776 return(proc_len);
778 acs_invalid:
779 if (acsp)
780 UM_FREE(acsp);
781 return(0);
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.
790 * Arguments:
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
795 * Returns:
796 * 0 input was invalid
797 * else length of CSU Req message processed
800 static int
801 scsp_parse_csu(char *buff, int pdu_len, Scsp_csu_msg **csupp)
803 int i, len, proc_len;
804 Scsp_csu_msg *csup;
805 Scsp_csa **csapp;
808 * Get memory for the returned structure
810 csup = (Scsp_csu_msg *)UM_ALLOC(sizeof(Scsp_csu_msg));
811 if (!csup) {
812 goto csu_invalid;
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);
820 if (len == 0)
821 goto csu_invalid;
822 buff += len;
823 proc_len = len;
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);
832 buff += len;
833 proc_len += len;
837 * Set the address of the CSU Req message and
838 * return the length of processed data
840 *csupp = csup;
841 return(proc_len);
843 csu_invalid:
844 if (csup)
845 scsp_free_csu(csup);
846 return(0);
851 * Parse a Hello message
853 * Arguments:
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
858 * Returns:
859 * 0 input was invalid
860 * else length of Hello message processed
863 static int
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;
868 Scsp_hello *hp;
869 Scsp_id *idp;
870 Scsp_id **ridpp;
873 * Get memory for the returned structure
875 hp = (Scsp_hello *)UM_ALLOC(sizeof(Scsp_hello));
876 if (!hp) {
877 goto hello_invalid;
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);
892 * Get the family ID
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);
901 buff += proc_len;
902 len = scsp_parse_mcp(buff, pdu_len - proc_len,
903 &hp->hello_mcp);
904 if (len == 0)
905 goto hello_invalid;
906 buff += len;
907 proc_len += 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));
916 if (!idp) {
917 goto hello_invalid;
919 UM_ZERO(idp, sizeof(Scsp_id));
920 len = scsp_parse_id(buff,
921 hp->hello_mcp.rid.id_len,
922 idp);
923 if (len == 0) {
924 UM_FREE(idp);
925 goto hello_invalid;
927 buff += len;
928 proc_len += len;
929 *ridpp = idp;
933 * Set the address of the CA message and
934 * return the length of processed data
936 *hpp = hp;
937 return(proc_len);
939 hello_invalid:
940 if (hp)
941 scsp_free_hello(hp);
942 return(0);
947 * Parse an SCSP input packet
949 * Arguments:
950 * buff pointer to input packet
951 * pdu_len length of input packet
953 * Returns:
954 * NULL input packet was invalid
955 * else pointer to packet in internal format
958 Scsp_msg *
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;
964 Scsp_ext **expp;
967 * Check the message checksum
969 if (ip_checksum(buff, pdu_len) != 0) {
971 * Checksum was bad--discard the message
973 goto ignore;
977 * Allocate storage for the message
979 msg = (Scsp_msg *)UM_ALLOC(sizeof(Scsp_msg));
980 if (!msg) {
981 goto ignore;
983 UM_ZERO(msg, sizeof(Scsp_msg));
986 * Decode the fixed header
988 * Check the version
990 shp = (struct scsp_nhdr *)buff;
991 if (shp->sh_ver != SCSP_VER_1)
992 goto ignore;
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);
1003 if (len != pdu_len)
1004 goto ignore;
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) {
1017 case SCSP_CA_MSG:
1018 plen = scsp_parse_ca(buff, len, &msg->sc_ca);
1019 break;
1020 case SCSP_CSU_REQ_MSG:
1021 case SCSP_CSU_REPLY_MSG:
1022 case SCSP_CSUS_MSG:
1023 plen = scsp_parse_csu(buff, len, &msg->sc_csu_msg);
1024 break;
1025 case SCSP_HELLO_MSG:
1026 plen = scsp_parse_hello(buff, len, &msg->sc_hello);
1027 break;
1028 default:
1029 goto ignore;
1031 if (plen == 0) {
1032 goto ignore;
1034 buff += plen;
1035 len -= plen;
1038 * Decode any extensions
1040 if (ext_off != 0) {
1041 for (expp = &msg->sc_ext; len > 0;
1042 expp = &(*expp)->next) {
1043 plen = scsp_parse_ext(buff, len, expp);
1044 if (plen == 0) {
1045 goto ignore;
1047 buff += plen;
1048 len -= plen;
1053 * Make sure we handled the whole message
1055 if (len != 0) {
1056 goto ignore;
1060 * Return the address of the SCSP message in internal format
1062 return(msg);
1064 ignore:
1065 if (msg)
1066 scsp_free_msg(msg);
1067 return NULL;