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 $
31 * Server Cache Synchronization Protocol (SCSP) Support
32 * ----------------------------------------------------
34 * Output 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>
65 __RCSID("@(#) $FreeBSD: src/usr.sbin/atm/scspd/scsp_output.c,v 1.3 1999/08/28 01:15:33 peter Exp $");
70 * Put a long integer into the output buffer
72 * This routine is provided for cases where long ints may not be
73 * word-aligned in the output buffer.
77 * cp pointer to output buffer
91 * Convert to network order and copy to output buffer
94 UM_COPY(&nl, cp, sizeof(u_long));
99 * Format a Sender or Receiver ID
102 * idp ponter to ID structure
106 * 0 input was invalid
107 * else length of ID processed
111 scsp_format_id(idp, buff)
118 UM_COPY(idp->id, buff, idp->id_len);
121 * Return the ID length
128 * Format the Mandatory Common Part of an SCSP input packet
132 * buff pointer to mandatory common part
135 * 0 input was invalid
136 * else length of MCP in message
140 scsp_format_mcp(mcp, buff)
146 struct scsp_nmcp *smp;
149 * Set the protocol ID
151 smp = (struct scsp_nmcp *)buff;
152 smp->sm_pid = htons(mcp->pid);
155 * Set the server group ID
157 smp->sm_sgid = htons(mcp->sgid);
162 smp->sm_flags = htons(mcp->flags);
165 * Set the sender ID and length
167 smp->sm_sid_len = mcp->sid.id_len;
168 odp = buff + sizeof(struct scsp_nmcp);
169 len = scsp_format_id(&mcp->sid, odp);
175 * Set the receiver ID and length
177 smp->sm_rid_len = mcp->rid.id_len;
178 odp += mcp->sid.id_len;
179 len = scsp_format_id(&mcp->rid, odp);
185 * Set the record count
187 smp->sm_rec_cnt = htons(mcp->rec_cnt);
190 * Return the length of data we processed
192 return(sizeof(struct scsp_nmcp) + mcp->sid.id_len +
201 * Format an Extension
204 * exp pointer to extension in internal format
205 * buff pointer to output buffer
206 * blen space available in buffer
209 * 0 input was invalid
210 * else length of extension processed
214 scsp_format_ext(exp, buff, blen)
219 struct scsp_next *sep;
222 * Make sure there's room in the buffer
224 if (blen < (sizeof(struct scsp_next) + exp->len))
230 sep = (struct scsp_next *)buff;
231 sep->se_type = htons(exp->type);
236 sep->se_len = htons(exp->len);
242 buff += sizeof(struct scsp_next);
243 UM_COPY((caddr_t)exp + sizeof(Scsp_ext),
249 * Return the number of bytes processed
251 return(sizeof(struct scsp_next) + exp->len);
256 * Format the ATMARP part of a CSA record
259 * acsp pointer to ATMARP protocol-specific CSA record
260 * buff pointer to output buffer
263 * 0 input was invalid
264 * else length of record processed
268 scsp_format_atmarp(acsp, buff)
269 Scsp_atmarp_csa *acsp;
274 struct scsp_atmarp_ncsa *sanp;
277 * Figure out how long PDU is going to be
279 pkt_len = sizeof(struct scsp_atmarp_ncsa);
280 switch (acsp->sa_sha.address_format) {
281 case T_ATM_ENDSYS_ADDR:
282 pkt_len += acsp->sa_sha.address_length;
285 case T_ATM_E164_ADDR:
286 pkt_len += acsp->sa_sha.address_length;
287 if (acsp->sa_ssa.address_format == T_ATM_ENDSYS_ADDR)
288 pkt_len += acsp->sa_ssa.address_length;
292 switch (acsp->sa_tha.address_format) {
293 case T_ATM_ENDSYS_ADDR:
294 pkt_len += acsp->sa_tha.address_length;
297 case T_ATM_E164_ADDR:
298 pkt_len += acsp->sa_tha.address_length;
299 if (acsp->sa_tha.address_format == T_ATM_ENDSYS_ADDR)
300 pkt_len += acsp->sa_tha.address_length;
304 if (acsp->sa_spa.s_addr != 0)
305 pkt_len += sizeof(struct in_addr);
307 if (acsp->sa_tpa.s_addr != 0)
308 pkt_len += sizeof(struct in_addr);
313 sanp = (struct scsp_atmarp_ncsa *)buff;
314 cp = (char *)sanp + sizeof(struct scsp_atmarp_ncsa);
319 sanp->sa_hrd = htons(ARP_ATMFORUM);
320 sanp->sa_pro = htons(ETHERTYPE_IP);
323 len = acsp->sa_sha.address_length;
324 switch (acsp->sa_sha.address_format) {
325 case T_ATM_ENDSYS_ADDR:
326 sanp->sa_shtl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
329 UM_COPY(acsp->sa_sha.address, cp, len);
335 case T_ATM_E164_ADDR:
336 sanp->sa_shtl = ARP_TL_E164 | (len & ARP_TL_LMASK);
339 UM_COPY(acsp->sa_sha.address, cp, len);
342 if (acsp->sa_ssa.address_format == T_ATM_ENDSYS_ADDR) {
343 len = acsp->sa_ssa.address_length;
344 sanp->sa_sstl = ARP_TL_NSAPA |
345 (len & ARP_TL_LMASK);
348 UM_COPY(acsp->sa_ssa.address, cp, len);
360 sanp->sa_state = acsp->sa_state;
364 if (acsp->sa_spa.s_addr != 0) {
365 sanp->sa_spln = sizeof(struct in_addr);
366 UM_COPY(&acsp->sa_spa, cp, sizeof(struct in_addr));
367 cp += sizeof(struct in_addr);
371 len = acsp->sa_tha.address_length;
372 switch (acsp->sa_tha.address_format) {
373 case T_ATM_ENDSYS_ADDR:
374 sanp->sa_thtl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
377 UM_COPY(acsp->sa_tha.address, cp, len);
383 case T_ATM_E164_ADDR:
384 sanp->sa_thtl = ARP_TL_E164 | (len & ARP_TL_LMASK);
387 UM_COPY(acsp->sa_tha.address, cp, len);
390 if (acsp->sa_tsa.address_format == T_ATM_ENDSYS_ADDR) {
391 len = acsp->sa_tha.address_length;
392 sanp->sa_tstl = ARP_TL_NSAPA |
393 (len & ARP_TL_LMASK);
396 UM_COPY(acsp->sa_tsa.address, cp, len);
408 if (acsp->sa_tpa.s_addr != 0) {
409 sanp->sa_tpln = sizeof(struct in_addr);
410 UM_COPY(&acsp->sa_tpa, cp, sizeof(struct in_addr));
418 * Format a Cache State Advertisement or Cache State Advertisement
422 * csapp pointer to CSA or CSAS
423 * buff pointer to output buffer
426 * 0 input was invalid
427 * else length of record processed
431 scsp_format_csa(csap, buff)
437 struct scsp_ncsa *scp;
442 scp = (struct scsp_ncsa *)buff;
443 scp->scs_hop_cnt = htons(csap->hops);
449 scp->scs_nfill = htons(SCSP_CSAS_NULL);
453 * Set the sequence number
455 put_long(csap->seq, (u_char *)&scp->scs_seq);
460 scp->scs_ck_len = csap->key.key_len;
461 odp = buff + sizeof(struct scsp_ncsa);
462 UM_COPY(csap->key.key, odp, scp->scs_ck_len);
465 * Set the originator ID
467 odp += scp->scs_ck_len;
468 scp->scs_oid_len = scsp_format_id(&csap->oid, odp);
471 * Set the protocol-specific data, if present. At the
472 * moment, we only handle data for ATMARP.
474 if (csap->atmarp_data) {
475 odp += scp->scs_oid_len;
476 len = scsp_format_atmarp(csap->atmarp_data, odp);
480 * Set the record length
482 scp->scs_len = htons(sizeof(struct scsp_ncsa) +
483 scp->scs_ck_len + scp->scs_oid_len +
487 * Return the length of data we processed
489 return(ntohs(scp->scs_len));
494 * Format a Cache Alignment message
497 * cap pointer to CA message
498 * buff pointer to output buffer
499 * blen space available in buffer
502 * 0 input was invalid
503 * else length of CA message processed
507 scsp_format_ca(cap, buff, blen)
512 int i, len, proc_len;
513 struct scsp_nca *scap;
517 * Set the sequence number
519 scap = (struct scsp_nca *)buff;
520 put_long(cap->ca_seq, (u_char *)&scap->sca_seq);
521 proc_len = sizeof(scap->sca_seq);
522 buff += sizeof(scap->sca_seq);
527 cap->ca_mcp.flags = 0;
529 cap->ca_mcp.flags |= SCSP_CA_M;
531 cap->ca_mcp.flags |= SCSP_CA_I;
533 cap->ca_mcp.flags |= SCSP_CA_O;
536 * Format the mandatory common part of the message
538 len = scsp_format_mcp(&cap->ca_mcp, buff);
545 * Put any CSAS records into the message
547 for (i = 0, csap = cap->ca_csa_rec; i < cap->ca_mcp.rec_cnt;
548 i++, csap = csap->next) {
549 len = scsp_format_csa(csap, buff);
552 if (proc_len > blen) {
553 scsp_log(LOG_CRIT, "scsp_format_ca: buffer overflow");
559 * Return the length of processed data
569 * Format a Cache State Update Request, Cache State Update Reply, or
570 * Cache State Update Solicit message. These all have the same format,
571 * a Mandatory Common Part followed by a number of CSA or CSAS records.
574 * csup pointer to location to put pointer to CSU Req message
575 * buff pointer to output buffer
576 * blen space available in buffer
579 * 0 input was invalid
580 * else length of CSU Req message processed
584 scsp_format_csu(csup, buff, blen)
589 int i, len, proc_len;
590 struct scsp_ncsu_msg *scsup;
594 * Format the mandatory common part of the message
596 scsup = (struct scsp_ncsu_msg *)buff;
597 len = scsp_format_mcp(&csup->csu_mcp, buff);
604 * Put the CSAS records into the message
606 for (i = 0, csap = csup->csu_csa_rec;
607 i < csup->csu_mcp.rec_cnt && csap;
608 i++, csap = csap->next) {
609 len = scsp_format_csa(csap, buff);
612 if (proc_len > blen) {
613 scsp_log(LOG_CRIT, "scsp_format_csu: buffer overflow");
619 * Return the length of processed data
629 * Format a Hello message
632 * hpp pointer to Hello message
633 * buff pointer to output buffer
634 * blen space available in buffer
637 * 0 input was invalid
638 * else length of Hello message processed
642 scsp_format_hello(hp, buff, blen)
648 struct scsp_nhello *shp;
652 * Set the hello interval
654 shp = (struct scsp_nhello *)buff;
655 shp->sch_hi = htons(hp->hello_int);
658 * Set the dead factor
660 shp->sch_df = htons(hp->dead_factor);
665 shp->sch_fid = htons(hp->family_id);
668 * Process the mandatory common part of the message
670 proc_len = sizeof(struct scsp_nhello) -
671 sizeof(struct scsp_nmcp);
673 len = scsp_format_mcp(&hp->hello_mcp, buff);
680 * Add any additional receiver ID records to the message
682 for (ridp = hp->hello_mcp.rid.next; ridp;
684 len = scsp_format_id(ridp, buff);
693 * Return the length of the Hello message body
695 if (proc_len > blen) {
696 scsp_log(LOG_CRIT, "scsp_format_hello: buffer overflow");
707 * Format an SCSP output packet
710 * dcsp pointer to DCS for which message is being prepared
711 * msg pointer to input packet
712 * bpp pointer to location to put pointer to formatted packet
715 * 0 input packet was invalid
716 * else length of formatted packet
720 scsp_format_msg(dcsp, msg, bpp)
725 char *buff = (char *)0, *e_buff = (char *)0;
726 int buff_len, e_buff_len;
727 int e_len, len, plen;
728 struct scsp_nhdr *shp;
732 * Allocate a buffer for the message
734 buff_len = dcsp->sd_server->ss_mtu;
735 buff = (char *)UM_ALLOC(buff_len);
737 scsp_mem_err("scsp_format_msg: dcsp->sd_server->ss_mtu");
739 UM_ZERO(buff, buff_len);
743 * Encode the fixed header
747 shp = (struct scsp_nhdr *)buff;
748 shp->sh_ver = SCSP_VER_1;
751 * Set the message type
753 shp->sh_type = msg->sc_msg_type;
756 * Point past the fixed header
758 len = sizeof(struct scsp_nhdr);
762 * Encode any extensions into a temporary buffer
767 * Get a buffer for the extensions
770 e_buff = (char *)UM_ALLOC(e_buff_len);
772 scsp_mem_err("scsp_format_msg: e_buff_len");
774 UM_ZERO(e_buff, e_buff_len);
777 * Encode the extensions
779 for (exp = msg->sc_ext = 0; exp; exp = exp->next) {
780 plen = scsp_format_ext(exp, e_buff + e_len,
789 * Free the buffer if we didn't use it
799 * Encode the body of the message, depending on the type
801 switch(msg->sc_msg_type) {
803 plen = scsp_format_ca(msg->sc_ca, buff + len, buff_len);
805 case SCSP_CSU_REQ_MSG:
806 case SCSP_CSU_REPLY_MSG:
808 plen = scsp_format_csu(msg->sc_csu_msg, buff + len,
812 plen = scsp_format_hello(msg->sc_hello, buff + len,
824 * Copy the extensions to the end of the message
827 shp->sh_ext_off = htons(len);
828 UM_COPY(e_buff, buff + len, e_len);
835 shp->sh_len = htons(len);
838 * Compute the message checksum
840 shp->sh_checksum = htons(ip_checksum(buff, len));
843 * Return the length of the buffer
858 * Send an SCSP message
861 * dcsp pointer to DCS control block
862 * msg pointer to message to send
866 * errno error encountered
870 scsp_send_msg(dcsp, msg)
878 * Make sure we have a socket open
880 if (dcsp->sd_sock == -1) {
887 if (((scsp_trace_mode & SCSP_TRACE_HELLO_MSG) &&
888 msg->sc_msg_type == SCSP_HELLO_MSG) ||
889 ((scsp_trace_mode & SCSP_TRACE_CA_MSG) &&
890 msg->sc_msg_type != SCSP_HELLO_MSG)) {
891 scsp_trace_msg(dcsp, msg, 0);
896 * Put the message into network format
898 len = scsp_format_msg(dcsp, msg, &buff);
900 scsp_log(LOG_ERR, "scsp_send_msg: message conversion failed\n");
905 * Write the message to the DCS
907 rc = write(dcsp->sd_sock, (void *)buff, len);
909 if (rc == len || (rc == -1 && errno == EINPROGRESS)) {
913 * There was an error on the write--close the VCC
915 (void)close(dcsp->sd_sock);
919 * Inform the Hello FSM
921 (void)scsp_hfsm(dcsp, SCSP_HFSM_VC_CLOSED,
925 * Set the return code