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_output.c,v 1.3 1999/08/28 01:15:33 peter Exp $
30 * Server Cache Synchronization Protocol (SCSP) Support
31 * ----------------------------------------------------
33 * Output packet processing
37 #include <sys/types.h>
38 #include <sys/param.h>
39 #include <sys/socket.h>
40 #include <net/ethernet.h>
42 #include <netinet/in.h>
43 #include <netatm/port.h>
44 #include <netatm/queue.h>
45 #include <netatm/atm.h>
46 #include <netatm/atm_if.h>
47 #include <netatm/atm_sap.h>
48 #include <netatm/atm_sys.h>
49 #include <netatm/atm_ioctl.h>
64 * Put a long integer into the output buffer
66 * This routine is provided for cases where long ints may not be
67 * word-aligned in the output buffer.
71 * cp pointer to output buffer
78 put_long(u_long l, u_char *cp)
83 * Convert to network order and copy to output buffer
86 UM_COPY(&nl, cp, sizeof(u_long));
91 * Format a Sender or Receiver ID
94 * idp ponter to ID structure
99 * else length of ID processed
103 scsp_format_id(Scsp_id *idp, char *buff)
108 UM_COPY(idp->id, buff, idp->id_len);
111 * Return the ID length
118 * Format the Mandatory Common Part of an SCSP input packet
122 * buff pointer to mandatory common part
125 * 0 input was invalid
126 * else length of MCP in message
130 scsp_format_mcp(Scsp_mcp *mcp, char *buff)
134 struct scsp_nmcp *smp;
137 * Set the protocol ID
139 smp = (struct scsp_nmcp *)buff;
140 smp->sm_pid = htons(mcp->pid);
143 * Set the server group ID
145 smp->sm_sgid = htons(mcp->sgid);
150 smp->sm_flags = htons(mcp->flags);
153 * Set the sender ID and length
155 smp->sm_sid_len = mcp->sid.id_len;
156 odp = buff + sizeof(struct scsp_nmcp);
157 len = scsp_format_id(&mcp->sid, odp);
163 * Set the receiver ID and length
165 smp->sm_rid_len = mcp->rid.id_len;
166 odp += mcp->sid.id_len;
167 len = scsp_format_id(&mcp->rid, odp);
173 * Set the record count
175 smp->sm_rec_cnt = htons(mcp->rec_cnt);
178 * Return the length of data we processed
180 return(sizeof(struct scsp_nmcp) + mcp->sid.id_len +
189 * Format an Extension
192 * exp pointer to extension in internal format
193 * buff pointer to output buffer
194 * blen space available in buffer
197 * 0 input was invalid
198 * else length of extension processed
202 scsp_format_ext(Scsp_ext *exp, char *buff, int blen)
204 struct scsp_next *sep;
207 * Make sure there's room in the buffer
209 if (blen < (sizeof(struct scsp_next) + exp->len))
215 sep = (struct scsp_next *)buff;
216 sep->se_type = htons(exp->type);
221 sep->se_len = htons(exp->len);
227 buff += sizeof(struct scsp_next);
228 UM_COPY((caddr_t)exp + sizeof(Scsp_ext),
234 * Return the number of bytes processed
236 return(sizeof(struct scsp_next) + exp->len);
241 * Format the ATMARP part of a CSA record
244 * acsp pointer to ATMARP protocol-specific CSA record
245 * buff pointer to output buffer
248 * 0 input was invalid
249 * else length of record processed
253 scsp_format_atmarp(Scsp_atmarp_csa *acsp, char *buff)
257 struct scsp_atmarp_ncsa *sanp;
260 * Figure out how long PDU is going to be
262 pkt_len = sizeof(struct scsp_atmarp_ncsa);
263 switch (acsp->sa_sha.address_format) {
264 case T_ATM_ENDSYS_ADDR:
265 pkt_len += acsp->sa_sha.address_length;
268 case T_ATM_E164_ADDR:
269 pkt_len += acsp->sa_sha.address_length;
270 if (acsp->sa_ssa.address_format == T_ATM_ENDSYS_ADDR)
271 pkt_len += acsp->sa_ssa.address_length;
275 switch (acsp->sa_tha.address_format) {
276 case T_ATM_ENDSYS_ADDR:
277 pkt_len += acsp->sa_tha.address_length;
280 case T_ATM_E164_ADDR:
281 pkt_len += acsp->sa_tha.address_length;
282 if (acsp->sa_tha.address_format == T_ATM_ENDSYS_ADDR)
283 pkt_len += acsp->sa_tha.address_length;
287 if (acsp->sa_spa.s_addr != 0)
288 pkt_len += sizeof(struct in_addr);
290 if (acsp->sa_tpa.s_addr != 0)
291 pkt_len += sizeof(struct in_addr);
296 sanp = (struct scsp_atmarp_ncsa *)buff;
297 cp = (char *)sanp + sizeof(struct scsp_atmarp_ncsa);
302 sanp->sa_hrd = htons(ARP_ATMFORUM);
303 sanp->sa_pro = htons(ETHERTYPE_IP);
306 len = acsp->sa_sha.address_length;
307 switch (acsp->sa_sha.address_format) {
308 case T_ATM_ENDSYS_ADDR:
309 sanp->sa_shtl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
312 UM_COPY(acsp->sa_sha.address, cp, len);
318 case T_ATM_E164_ADDR:
319 sanp->sa_shtl = ARP_TL_E164 | (len & ARP_TL_LMASK);
322 UM_COPY(acsp->sa_sha.address, cp, len);
325 if (acsp->sa_ssa.address_format == T_ATM_ENDSYS_ADDR) {
326 len = acsp->sa_ssa.address_length;
327 sanp->sa_sstl = ARP_TL_NSAPA |
328 (len & ARP_TL_LMASK);
331 UM_COPY(acsp->sa_ssa.address, cp, len);
343 sanp->sa_state = acsp->sa_state;
347 if (acsp->sa_spa.s_addr != 0) {
348 sanp->sa_spln = sizeof(struct in_addr);
349 UM_COPY(&acsp->sa_spa, cp, sizeof(struct in_addr));
350 cp += sizeof(struct in_addr);
354 len = acsp->sa_tha.address_length;
355 switch (acsp->sa_tha.address_format) {
356 case T_ATM_ENDSYS_ADDR:
357 sanp->sa_thtl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
360 UM_COPY(acsp->sa_tha.address, cp, len);
366 case T_ATM_E164_ADDR:
367 sanp->sa_thtl = ARP_TL_E164 | (len & ARP_TL_LMASK);
370 UM_COPY(acsp->sa_tha.address, cp, len);
373 if (acsp->sa_tsa.address_format == T_ATM_ENDSYS_ADDR) {
374 len = acsp->sa_tha.address_length;
375 sanp->sa_tstl = ARP_TL_NSAPA |
376 (len & ARP_TL_LMASK);
379 UM_COPY(acsp->sa_tsa.address, cp, len);
391 if (acsp->sa_tpa.s_addr != 0) {
392 sanp->sa_tpln = sizeof(struct in_addr);
393 UM_COPY(&acsp->sa_tpa, cp, sizeof(struct in_addr));
401 * Format a Cache State Advertisement or Cache State Advertisement
405 * csapp pointer to CSA or CSAS
406 * buff pointer to output buffer
409 * 0 input was invalid
410 * else length of record processed
414 scsp_format_csa(Scsp_csa *csap, char *buff)
418 struct scsp_ncsa *scp;
423 scp = (struct scsp_ncsa *)buff;
424 scp->scs_hop_cnt = htons(csap->hops);
430 scp->scs_nfill = htons(SCSP_CSAS_NULL);
434 * Set the sequence number
436 put_long(csap->seq, (u_char *)&scp->scs_seq);
441 scp->scs_ck_len = csap->key.key_len;
442 odp = buff + sizeof(struct scsp_ncsa);
443 UM_COPY(csap->key.key, odp, scp->scs_ck_len);
446 * Set the originator ID
448 odp += scp->scs_ck_len;
449 scp->scs_oid_len = scsp_format_id(&csap->oid, odp);
452 * Set the protocol-specific data, if present. At the
453 * moment, we only handle data for ATMARP.
455 if (csap->atmarp_data) {
456 odp += scp->scs_oid_len;
457 len = scsp_format_atmarp(csap->atmarp_data, odp);
461 * Set the record length
463 scp->scs_len = htons(sizeof(struct scsp_ncsa) +
464 scp->scs_ck_len + scp->scs_oid_len +
468 * Return the length of data we processed
470 return(ntohs(scp->scs_len));
475 * Format a Cache Alignment message
478 * cap pointer to CA message
479 * buff pointer to output buffer
480 * blen space available in buffer
483 * 0 input was invalid
484 * else length of CA message processed
488 scsp_format_ca(Scsp_ca *cap, char *buff, int blen)
490 int i, len, proc_len;
491 struct scsp_nca *scap;
495 * Set the sequence number
497 scap = (struct scsp_nca *)buff;
498 put_long(cap->ca_seq, (u_char *)&scap->sca_seq);
499 proc_len = sizeof(scap->sca_seq);
500 buff += sizeof(scap->sca_seq);
505 cap->ca_mcp.flags = 0;
507 cap->ca_mcp.flags |= SCSP_CA_M;
509 cap->ca_mcp.flags |= SCSP_CA_I;
511 cap->ca_mcp.flags |= SCSP_CA_O;
514 * Format the mandatory common part of the message
516 len = scsp_format_mcp(&cap->ca_mcp, buff);
523 * Put any CSAS records into the message
525 for (i = 0, csap = cap->ca_csa_rec; i < cap->ca_mcp.rec_cnt;
526 i++, csap = csap->next) {
527 len = scsp_format_csa(csap, buff);
530 if (proc_len > blen) {
531 scsp_log(LOG_CRIT, "scsp_format_ca: buffer overflow");
537 * Return the length of processed data
547 * Format a Cache State Update Request, Cache State Update Reply, or
548 * Cache State Update Solicit message. These all have the same format,
549 * a Mandatory Common Part followed by a number of CSA or CSAS records.
552 * csup pointer to location to put pointer to CSU Req message
553 * buff pointer to output buffer
554 * blen space available in buffer
557 * 0 input was invalid
558 * else length of CSU Req message processed
562 scsp_format_csu(Scsp_csu_msg *csup, char *buff, int blen)
564 int i, len, proc_len;
568 * Format the mandatory common part of the message
570 len = scsp_format_mcp(&csup->csu_mcp, buff);
577 * Put the CSAS records into the message
579 for (i = 0, csap = csup->csu_csa_rec;
580 i < csup->csu_mcp.rec_cnt && csap;
581 i++, csap = csap->next) {
582 len = scsp_format_csa(csap, buff);
585 if (proc_len > blen) {
586 scsp_log(LOG_CRIT, "scsp_format_csu: buffer overflow");
592 * Return the length of processed data
602 * Format a Hello message
605 * hpp pointer to Hello message
606 * buff pointer to output buffer
607 * blen space available in buffer
610 * 0 input was invalid
611 * else length of Hello message processed
615 scsp_format_hello(Scsp_hello *hp, char *buff, int blen)
618 struct scsp_nhello *shp;
622 * Set the hello interval
624 shp = (struct scsp_nhello *)buff;
625 shp->sch_hi = htons(hp->hello_int);
628 * Set the dead factor
630 shp->sch_df = htons(hp->dead_factor);
635 shp->sch_fid = htons(hp->family_id);
638 * Process the mandatory common part of the message
640 proc_len = sizeof(struct scsp_nhello) -
641 sizeof(struct scsp_nmcp);
643 len = scsp_format_mcp(&hp->hello_mcp, buff);
650 * Add any additional receiver ID records to the message
652 for (ridp = hp->hello_mcp.rid.next; ridp;
654 len = scsp_format_id(ridp, buff);
663 * Return the length of the Hello message body
665 if (proc_len > blen) {
666 scsp_log(LOG_CRIT, "scsp_format_hello: buffer overflow");
677 * Format an SCSP output packet
680 * dcsp pointer to DCS for which message is being prepared
681 * msg pointer to input packet
682 * bpp pointer to location to put pointer to formatted packet
685 * 0 input packet was invalid
686 * else length of formatted packet
690 scsp_format_msg(Scsp_dcs *dcsp, Scsp_msg *msg, char **bpp)
692 char *buff = NULL, *e_buff = NULL;
693 int buff_len, e_buff_len;
694 int e_len, len, plen;
695 struct scsp_nhdr *shp;
699 * Allocate a buffer for the message
701 buff_len = dcsp->sd_server->ss_mtu;
702 buff = (char *)UM_ALLOC(buff_len);
704 scsp_mem_err("scsp_format_msg: dcsp->sd_server->ss_mtu");
706 UM_ZERO(buff, buff_len);
710 * Encode the fixed header
714 shp = (struct scsp_nhdr *)buff;
715 shp->sh_ver = SCSP_VER_1;
718 * Set the message type
720 shp->sh_type = msg->sc_msg_type;
723 * Point past the fixed header
725 len = sizeof(struct scsp_nhdr);
729 * Encode any extensions into a temporary buffer
734 * Get a buffer for the extensions
737 e_buff = (char *)UM_ALLOC(e_buff_len);
739 scsp_mem_err("scsp_format_msg: e_buff_len");
741 UM_ZERO(e_buff, e_buff_len);
744 * Encode the extensions
746 for (exp = msg->sc_ext = 0; exp; exp = exp->next) {
747 plen = scsp_format_ext(exp, e_buff + e_len,
756 * Free the buffer if we didn't use it
766 * Encode the body of the message, depending on the type
768 switch(msg->sc_msg_type) {
770 plen = scsp_format_ca(msg->sc_ca, buff + len, buff_len);
772 case SCSP_CSU_REQ_MSG:
773 case SCSP_CSU_REPLY_MSG:
775 plen = scsp_format_csu(msg->sc_csu_msg, buff + len,
779 plen = scsp_format_hello(msg->sc_hello, buff + len,
791 * Copy the extensions to the end of the message
794 shp->sh_ext_off = htons(len);
795 UM_COPY(e_buff, buff + len, e_len);
802 shp->sh_len = htons(len);
805 * Compute the message checksum
807 shp->sh_checksum = htons(ip_checksum(buff, len));
810 * Return the length of the buffer
825 * Send an SCSP message
828 * dcsp pointer to DCS control block
829 * msg pointer to message to send
833 * errno error encountered
837 scsp_send_msg(Scsp_dcs *dcsp, Scsp_msg *msg)
843 * Make sure we have a socket open
845 if (dcsp->sd_sock == -1) {
852 if (((scsp_trace_mode & SCSP_TRACE_HELLO_MSG) &&
853 msg->sc_msg_type == SCSP_HELLO_MSG) ||
854 ((scsp_trace_mode & SCSP_TRACE_CA_MSG) &&
855 msg->sc_msg_type != SCSP_HELLO_MSG)) {
856 scsp_trace_msg(dcsp, msg, 0);
861 * Put the message into network format
863 len = scsp_format_msg(dcsp, msg, &buff);
865 scsp_log(LOG_ERR, "scsp_send_msg: message conversion failed\n");
870 * Write the message to the DCS
872 rc = write(dcsp->sd_sock, (void *)buff, len);
874 if (rc == len || (rc == -1 && errno == EINPROGRESS)) {
878 * There was an error on the write--close the VCC
880 close(dcsp->sd_sock);
884 * Inform the Hello FSM
886 scsp_hfsm(dcsp, SCSP_HFSM_VC_CLOSED, NULL);
889 * Set the return code