Testing - fix bugs in fsx related to 64-bit systems.
[dragonfly.git] / usr.sbin / atm / scspd / scsp_socket.c
blob974532e9d0c8610f9366558e36e77f547c4d69ff
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_socket.c,v 1.3 1999/08/28 01:15:34 peter Exp $
27 * @(#) $DragonFly: src/usr.sbin/atm/scspd/scsp_socket.c,v 1.5 2006/08/03 16:40:48 swildner Exp $
32 * Server Cache Synchronization Protocol (SCSP) Support
33 * ----------------------------------------------------
35 * SCSP socket management routines
39 #include <sys/types.h>
40 #include <sys/param.h>
41 #include <sys/socket.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 <fcntl.h>
54 #include <libatm.h>
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <string.h>
58 #include <syslog.h>
59 #include <unistd.h>
61 #include "scsp_msg.h"
62 #include "scsp_if.h"
63 #include "scsp_var.h"
66 * Local variables
68 static struct t_atm_llc llc_scsp = {
69 T_ATM_LLC_SHARING,
71 {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x5e, 0x00, 0x05}
74 static struct t_atm_aal5 aal5 = {
75 0, /* forward_max_SDU_size */
76 0, /* backward_max_SDU_size */
77 0 /* SSCS_type */
80 static struct t_atm_traffic traffic = {
81 { /* forward */
82 T_ATM_ABSENT, /* PCR_high_priority */
83 0, /* PCR_all_traffic */
84 T_ATM_ABSENT, /* SCR_high_priority */
85 T_ATM_ABSENT, /* SCR_all_traffic */
86 T_ATM_ABSENT, /* MBS_high_priority */
87 T_ATM_ABSENT, /* MBS_all_traffic */
88 T_NO /* tagging */
90 { /* backward */
91 T_ATM_ABSENT, /* PCR_high_priority */
92 0, /* PCR_all_traffic */
93 T_ATM_ABSENT, /* SCR_high_priority */
94 T_ATM_ABSENT, /* SCR_all_traffic */
95 T_ATM_ABSENT, /* MBS_high_priority */
96 T_ATM_ABSENT, /* MBS_all_traffic */
97 T_NO /* tagging */
99 T_YES /* best_effort */
102 static struct t_atm_bearer bearer = {
103 T_ATM_CLASS_X, /* bearer_class */
104 T_ATM_NULL, /* traffic_type */
105 T_ATM_NULL, /* timing_requirements */
106 T_NO, /* clipping_susceptibility */
107 T_ATM_1_TO_1 /* connection_configuration */
110 static struct t_atm_qos qos = {
111 T_ATM_NETWORK_CODING, /* coding_standard */
112 { /* forward */
113 T_ATM_QOS_CLASS_0 /* qos_class */
115 { /* backward */
116 T_ATM_QOS_CLASS_0 /* qos_class */
120 static struct t_atm_app_name appname = {
121 "SCSP"
126 * Find a DCS, given its socket
128 * Arguments:
129 * sd socket descriptor
131 * Returns:
132 * 0 not found
133 * address of DCS block corresponding to socket
136 Scsp_dcs *
137 scsp_find_dcs(int sd)
139 Scsp_server *ssp;
140 Scsp_dcs *dcsp = NULL;
143 * Loop through the list of servers
145 for (ssp = scsp_server_head; ssp; ssp = ssp->ss_next) {
147 * Check all the DCSs chained from each server
149 for (dcsp = ssp->ss_dcs; dcsp; dcsp = dcsp->sd_next) {
150 if (dcsp->sd_sock == sd)
151 break;
155 return(dcsp);
160 * Find a server, given its socket
162 * Arguments:
163 * sd socket descriptor
165 * Returns:
166 * 0 not found
167 * address of server block corresponding to socket
170 Scsp_server *
171 scsp_find_server(int sd)
173 Scsp_server *ssp;
176 * Loop through the list of servers
178 for (ssp = scsp_server_head; ssp; ssp = ssp->ss_next) {
179 if (ssp->ss_sock == sd)
180 break;
183 return(ssp);
188 * Connect to a directly connected server
190 * Arguments:
191 * dcsp pointer to DCS block for server
193 * Returns:
194 * 0 success (dcsp->sd_sock is set)
195 * else errno indicating reason for failure
199 scsp_dcs_connect(Scsp_dcs *dcsp)
202 int rc, sd;
203 struct sockaddr_atm DCS_addr;
206 * If the DCS already has an open connection, just return
208 if (dcsp->sd_sock != -1) {
209 return(0);
213 * Open an ATM socket
215 sd = socket(PF_ATM, SOCK_SEQPACKET, ATM_PROTO_AAL5);
216 if (sd == -1) {
217 return(ESOCKTNOSUPPORT);
219 if (sd > scsp_max_socket) {
220 scsp_max_socket = sd;
224 * Set up connection parameters for SCSP connection
226 UM_ZERO(&DCS_addr, sizeof(DCS_addr));
227 #if (defined(BSD) && (BSD >= 199103))
228 DCS_addr.satm_len = sizeof(DCS_addr);
229 #endif
230 DCS_addr.satm_family = AF_ATM;
231 DCS_addr.satm_addr.t_atm_sap_addr.SVE_tag_addr =
232 T_ATM_PRESENT;
233 DCS_addr.satm_addr.t_atm_sap_addr.SVE_tag_selector =
234 T_ATM_PRESENT;
235 DCS_addr.satm_addr.t_atm_sap_addr.address_format =
236 dcsp->sd_addr.address_format;
237 DCS_addr.satm_addr.t_atm_sap_addr.address_length =
238 dcsp->sd_addr.address_length;
239 UM_COPY(dcsp->sd_addr.address,
240 DCS_addr.satm_addr.t_atm_sap_addr.address,
241 dcsp->sd_addr.address_length);
243 DCS_addr.satm_addr.t_atm_sap_layer2.SVE_tag =
244 T_ATM_PRESENT;
245 DCS_addr.satm_addr.t_atm_sap_layer2.ID_type =
246 T_ATM_SIMPLE_ID;
247 DCS_addr.satm_addr.t_atm_sap_layer2.ID.simple_ID =
248 T_ATM_BLLI2_I8802;
250 DCS_addr.satm_addr.t_atm_sap_layer3.SVE_tag =
251 T_ATM_ABSENT;
252 DCS_addr.satm_addr.t_atm_sap_appl.SVE_tag =
253 T_ATM_ABSENT;
256 * Bind the socket to our address
258 if (bind(sd, (struct sockaddr *)&DCS_addr,
259 sizeof(DCS_addr))) {
260 rc = errno;
261 goto connect_fail;
265 * Set non-blocking operation
267 #ifdef sun
268 rc = fcntl(sd, F_SETFL, FNBIO + FNDELAY);
269 #else
270 rc = fcntl(sd, F_SETFL, O_NONBLOCK);
271 #endif
272 if (rc == -1) {
273 scsp_log(LOG_ERR, "scsp_dcs_connect: fcntl failed");
274 rc = errno;
275 goto connect_fail;
279 * Set AAL 5 options
281 aal5.forward_max_SDU_size = dcsp->sd_server->ss_mtu;
282 aal5.backward_max_SDU_size = dcsp->sd_server->ss_mtu;
283 if (setsockopt(sd, T_ATM_SIGNALING, T_ATM_AAL5, (caddr_t)&aal5,
284 sizeof(aal5)) < 0) {
285 rc = EOPNOTSUPP;
286 goto connect_fail;
290 * Set traffic options
292 switch(dcsp->sd_server->ss_media) {
293 case MEDIA_TAXI_100:
294 traffic.forward.PCR_all_traffic = ATM_PCR_TAXI100;
295 traffic.backward.PCR_all_traffic = ATM_PCR_TAXI100;
296 break;
297 case MEDIA_TAXI_140:
298 traffic.forward.PCR_all_traffic = ATM_PCR_TAXI140;
299 traffic.backward.PCR_all_traffic = ATM_PCR_TAXI140;
300 break;
301 case MEDIA_OC3C:
302 case MEDIA_UTP155:
303 traffic.forward.PCR_all_traffic = ATM_PCR_OC3C;
304 traffic.backward.PCR_all_traffic = ATM_PCR_OC3C;
305 break;
306 case MEDIA_OC12C:
307 traffic.forward.PCR_all_traffic = ATM_PCR_OC12C;
308 traffic.backward.PCR_all_traffic = ATM_PCR_OC12C;
309 break;
310 case MEDIA_UNKNOWN:
311 break;
314 if (setsockopt(sd, T_ATM_SIGNALING, T_ATM_TRAFFIC,
315 (caddr_t)&traffic, sizeof(traffic)) < 0) {
316 rc = EOPNOTSUPP;
317 goto connect_fail;
321 * Set bearer capability options
323 if (setsockopt(sd, T_ATM_SIGNALING, T_ATM_BEARER_CAP,
324 (caddr_t)&bearer, sizeof(bearer)) < 0) {
325 rc = EOPNOTSUPP;
326 goto connect_fail;
330 * Set QOS options
332 if (setsockopt(sd, T_ATM_SIGNALING, T_ATM_QOS,
333 (caddr_t)&qos, sizeof(qos)) < 0) {
334 rc = EOPNOTSUPP;
335 goto connect_fail;
339 * Set LLC identifier
341 if (setsockopt(sd, T_ATM_SIGNALING, T_ATM_LLC,
342 (caddr_t)&llc_scsp, sizeof(llc_scsp)) < 0) {
343 rc = EOPNOTSUPP;
344 goto connect_fail;
348 * Set application name
350 if (setsockopt(sd, T_ATM_SIGNALING, T_ATM_APP_NAME,
351 (caddr_t)&appname, sizeof(appname)) < 0) {
352 rc = EOPNOTSUPP;
353 goto connect_fail;
357 * Connect to DCS
359 if (connect(sd, (struct sockaddr *)&DCS_addr,
360 sizeof(DCS_addr)) < 0 &&
361 errno != EINPROGRESS) {
362 rc = errno;
363 goto connect_fail;
367 * Set return values
369 dcsp->sd_sock = sd;
370 return(0);
372 connect_fail:
374 * Close the socket if something didn't work
376 close(sd);
377 dcsp->sd_sock = -1;
378 if (rc == 0)
379 rc = EFAULT;
380 return(rc);
385 * Listen for ATM connections from DCSs
387 * Arguments:
388 * None
390 * Returns:
391 * sock socket which is listening (also set in
392 ssp->ss_dcs_lsock)
393 * -1 error encountered (reason in errno)
397 scsp_dcs_listen(Scsp_server *ssp)
399 int rc, sd;
400 struct sockaddr_atm ls_addr;
403 * Open a socket
405 sd = socket(PF_ATM, SOCK_SEQPACKET, ATM_PROTO_AAL5);
406 if (sd == -1) {
407 rc = errno;
408 goto listen_fail;
410 if (sd > scsp_max_socket) {
411 scsp_max_socket = sd;
415 * Set up our address
417 UM_ZERO(&ls_addr, sizeof(ls_addr));
418 #if (defined(BSD) && (BSD >= 199103))
419 ls_addr.satm_len = sizeof(ls_addr);
420 #endif
421 ls_addr.satm_family = AF_ATM;
422 ls_addr.satm_addr.t_atm_sap_addr.SVE_tag_addr = T_ATM_PRESENT;
423 ls_addr.satm_addr.t_atm_sap_addr.SVE_tag_selector =
424 T_ATM_PRESENT;
425 ls_addr.satm_addr.t_atm_sap_addr.address_format =
426 ssp->ss_addr.address_format;
427 ls_addr.satm_addr.t_atm_sap_addr.address_length =
428 ssp->ss_addr.address_length;
429 UM_COPY(ssp->ss_addr.address,
430 ls_addr.satm_addr.t_atm_sap_addr.address,
431 ssp->ss_addr.address_length);
433 ls_addr.satm_addr.t_atm_sap_layer2.SVE_tag = T_ATM_PRESENT;
434 ls_addr.satm_addr.t_atm_sap_layer2.ID_type = T_ATM_SIMPLE_ID;
435 ls_addr.satm_addr.t_atm_sap_layer2.ID.simple_ID =
436 T_ATM_BLLI2_I8802;
438 ls_addr.satm_addr.t_atm_sap_layer3.SVE_tag = T_ATM_ABSENT;
439 ls_addr.satm_addr.t_atm_sap_appl.SVE_tag = T_ATM_ABSENT;
442 * Bind the socket to our address
444 rc = bind(sd, (struct sockaddr *)&ls_addr, sizeof(ls_addr));
445 if (rc == -1) {
446 rc = errno;
447 goto listen_fail;
451 * Set non-blocking I/O
453 #ifdef sun
454 rc = fcntl(sd, F_SETFL, FNBIO + FNDELAY);
455 #else
456 rc = fcntl(sd, F_SETFL, O_NONBLOCK);
457 #endif
458 if (rc == -1) {
459 scsp_log(LOG_ERR, "scsp_dcs_listen: fcntl failed");
460 rc = errno;
461 goto listen_fail;
465 * Set AAL 5 options
467 aal5.forward_max_SDU_size = ssp->ss_mtu;
468 aal5.backward_max_SDU_size = ssp->ss_mtu;
469 if (setsockopt(sd, T_ATM_SIGNALING, T_ATM_AAL5, (caddr_t)&aal5,
470 sizeof(aal5)) < 0) {
471 rc = EOPNOTSUPP;
472 goto listen_fail;
476 * Set traffic options
478 switch(ssp->ss_media) {
479 case MEDIA_TAXI_100:
480 traffic.forward.PCR_all_traffic = ATM_PCR_TAXI100;
481 traffic.backward.PCR_all_traffic = ATM_PCR_TAXI100;
482 break;
483 case MEDIA_TAXI_140:
484 traffic.forward.PCR_all_traffic = ATM_PCR_TAXI140;
485 traffic.backward.PCR_all_traffic = ATM_PCR_TAXI140;
486 break;
487 case MEDIA_OC3C:
488 case MEDIA_UTP155:
489 traffic.forward.PCR_all_traffic = ATM_PCR_OC3C;
490 traffic.backward.PCR_all_traffic = ATM_PCR_OC3C;
491 break;
492 case MEDIA_OC12C:
493 traffic.forward.PCR_all_traffic = ATM_PCR_OC12C;
494 traffic.backward.PCR_all_traffic = ATM_PCR_OC12C;
495 break;
496 case MEDIA_UNKNOWN:
497 break;
500 if (setsockopt(sd, T_ATM_SIGNALING, T_ATM_TRAFFIC,
501 (caddr_t)&traffic, sizeof(traffic)) < 0) {
502 rc = EOPNOTSUPP;
503 goto listen_fail;
507 * Set bearer capability options
509 if (setsockopt(sd, T_ATM_SIGNALING, T_ATM_BEARER_CAP,
510 (caddr_t)&bearer, sizeof(bearer)) < 0) {
511 rc = EOPNOTSUPP;
512 goto listen_fail;
516 * Set QOS options
518 if (setsockopt(sd, T_ATM_SIGNALING, T_ATM_QOS,
519 (caddr_t)&qos, sizeof(qos)) < 0) {
520 rc = EOPNOTSUPP;
521 goto listen_fail;
525 * Set LLC identifier
527 if (setsockopt(sd, T_ATM_SIGNALING, T_ATM_LLC,
528 (caddr_t)&llc_scsp, sizeof(llc_scsp)) < 0) {
529 rc = EOPNOTSUPP;
530 goto listen_fail;
534 * Set application name
536 if (setsockopt(sd, T_ATM_SIGNALING, T_ATM_APP_NAME,
537 (caddr_t)&appname, sizeof(appname)) < 0) {
538 rc = EOPNOTSUPP;
539 goto listen_fail;
543 * Listen for new connections
545 if (listen(sd, 5) < 0) {
546 rc = errno;
547 goto listen_fail;
550 ssp->ss_dcs_lsock = sd;
551 return(sd);
553 listen_fail:
555 * Close the socket if anything didn't work
557 close(sd);
558 if (rc == 0)
559 errno = EFAULT;
560 else
561 errno = rc;
562 ssp->ss_dcs_lsock = -1;
563 return(-1);
568 * Accept a connection from a DCS
570 * Arguments:
571 * ssp pointer to server block
573 * Returns:
574 * address of DCS with new connection
575 * 0 failure (errno has reason)
578 Scsp_dcs *
579 scsp_dcs_accept(Scsp_server *ssp)
581 int len, rc, sd;
582 struct sockaddr_atm dcs_sockaddr;
583 struct t_atm_sap_addr *dcs_addr = &dcs_sockaddr.satm_addr.t_atm_sap_addr;
584 Atm_addr dcs_atmaddr;
585 Scsp_dcs *dcsp;
588 * Accept the new connection
590 len = sizeof(dcs_sockaddr);
591 sd = accept(ssp->ss_dcs_lsock,
592 (struct sockaddr *)&dcs_sockaddr, &len);
593 if (sd < 0) {
594 return(NULL);
596 if (sd > scsp_max_socket) {
597 scsp_max_socket = sd;
601 * Copy the DCS's address from the sockaddr to an Atm_addr
603 if (dcs_addr->SVE_tag_addr != T_ATM_PRESENT) {
604 dcs_atmaddr.address_format = T_ATM_ABSENT;
605 dcs_atmaddr.address_length = 0;
606 } else {
607 dcs_atmaddr.address_format = dcs_addr->address_format;
608 dcs_atmaddr.address_length = dcs_addr->address_length;
609 UM_COPY(dcs_addr->address, dcs_atmaddr.address,
610 dcs_addr->address_length);
614 * Find out which DCS this connection is for
616 for (dcsp = ssp->ss_dcs; dcsp; dcsp = dcsp->sd_next) {
618 * Compare DCS's address to address
619 * configured by user
621 if (ATM_ADDR_EQUAL(&dcsp->sd_addr,
622 &dcs_atmaddr))
623 break;
627 * Make sure we have this DCS configured
629 if (!dcsp) {
630 errno = EINVAL;
631 goto dcs_accept_fail;
635 * Make sure we are in a state to accept the connection
637 if (ssp->ss_state != SCSP_SS_ACTIVE) {
638 errno = EACCES;
639 goto dcs_accept_fail;
643 * Make sure we don't already have a connection to this DCS
645 if (dcsp->sd_sock != -1) {
646 errno = EALREADY;
647 goto dcs_accept_fail;
651 * Set application name
653 if (setsockopt(sd, T_ATM_SIGNALING, T_ATM_APP_NAME,
654 (caddr_t)&appname, sizeof(appname)) < 0) {
655 rc = EOPNOTSUPP;
656 goto dcs_accept_fail;
660 * Set non-blocking I/O
662 #ifdef sun
663 rc = fcntl(sd, F_SETFL, FNBIO + FNDELAY);
664 #else
665 rc = fcntl(sd, F_SETFL, O_NONBLOCK);
666 #endif
667 if (rc == -1) {
668 goto dcs_accept_fail;
672 * Cancel the open retry timer
674 HARP_CANCEL(&dcsp->sd_open_t);
677 * Save the socket address and return the
678 * address of the DCS
680 dcsp->sd_sock = sd;
681 return(dcsp);
683 dcs_accept_fail:
685 * An error has occured--clean up and return
687 close(sd);
688 return(NULL);
693 * Read an SCSP message from a directly connected server
695 * Arguments:
696 * dcsp pointer to DCS block that has data
698 * Returns:
699 * 0 success
700 * else errno indicating reason for failure
704 scsp_dcs_read(Scsp_dcs *dcsp)
706 int len, rc;
707 char *buff = NULL;
708 Scsp_server *ssp = dcsp->sd_server;
709 Scsp_msg *msg;
712 * Get a buffer to hold the entire message
714 len = ssp->ss_mtu;
715 buff = (char *)UM_ALLOC(len);
716 if (!buff) {
717 scsp_mem_err("scsp_dcs_read: ssp->ss_mtu");
721 * Read the message
723 len = read(dcsp->sd_sock, buff, len);
724 if (len < 0) {
725 goto dcs_read_fail;
729 * Parse the input message and pass it to the Hello FSM
731 msg = scsp_parse_msg(buff, len);
732 if (msg) {
734 * Write the message to the trace file if
735 * it's of a type we're tracing
737 if (((scsp_trace_mode & SCSP_TRACE_HELLO_MSG) &&
738 msg->sc_msg_type == SCSP_HELLO_MSG) ||
739 ((scsp_trace_mode & SCSP_TRACE_CA_MSG) &&
740 msg->sc_msg_type != SCSP_HELLO_MSG)) {
741 scsp_trace_msg(dcsp, msg, 1);
742 scsp_trace("\n");
746 * Pass the message to the Hello FSM
748 rc = scsp_hfsm(dcsp, SCSP_HFSM_RCVD, msg);
749 scsp_free_msg(msg);
750 } else {
752 * Message was invalid. Write it to the trace file
753 * if we're tracing messages.
755 if (scsp_trace_mode & (SCSP_TRACE_HELLO_MSG &
756 SCSP_TRACE_CA_MSG)) {
757 int i;
758 scsp_trace("Invalid message received:\n");
759 scsp_trace("0x");
760 for (i = 0; i < len; i++) {
761 scsp_trace("%02x ", (u_char)buff[i]);
763 scsp_trace("\n");
766 UM_FREE(buff);
768 return(0);
770 dcs_read_fail:
772 * Error on read--check for special conditions
774 rc = errno;
775 if (errno == ECONNRESET) {
777 * VCC has been closed--pass the event to
778 * the Hello FSM
780 rc = scsp_hfsm(dcsp, SCSP_HFSM_VC_CLOSED, NULL);
782 if (errno == ECONNREFUSED) {
784 * VCC open failed--set a timer and try
785 * again when it fires
787 HARP_TIMER(&dcsp->sd_open_t,
788 SCSP_Open_Interval,
789 scsp_open_timeout);
790 rc = 0;
793 if (buff)
794 UM_FREE(buff);
795 return(rc);
800 * Listen for Unix connections from SCSP client servers
802 * Arguments:
803 * None
805 * Returns:
806 * sock socket which is listening
807 * -1 error (reason in errno)
811 scsp_server_listen(void)
813 int rc, sd;
815 static struct sockaddr scsp_addr = {
816 #if (defined(BSD) && (BSD >= 199103))
817 sizeof(struct sockaddr), /* sa_len */
818 #endif
819 AF_UNIX, /* sa_family */
820 SCSPD_SOCK_NAME /* sa_data */
824 * Unlink any old socket
826 rc = unlink(SCSPD_SOCK_NAME);
827 if (rc < 0 && errno != ENOENT)
828 return(-1);
831 * Open a socket
833 sd = socket(PF_UNIX, SOCK_STREAM, 0);
834 if (sd == -1) {
835 return(-1);
837 if (sd > scsp_max_socket) {
838 scsp_max_socket = sd;
842 * Bind the socket's address
844 rc = bind(sd, &scsp_addr, sizeof(scsp_addr));
845 if (rc == -1) {
846 close(sd);
847 return(-1);
851 * Set non-blocking I/O
853 #ifdef sun
854 rc = fcntl(sd, F_SETFL, FNBIO + FNDELAY);
855 #else
856 rc = fcntl(sd, F_SETFL, O_NONBLOCK);
857 #endif
858 if (rc == -1) {
859 close(sd);
860 return(-1);
864 * Listen for new connections
866 if (listen(sd, 5) < 0) {
867 close(sd);
868 return(-1);
871 return(sd);
876 * Accept a connection from a server
878 * We accept a connection, but we won't know which server it is
879 * from until we get the configuration data from the server. We
880 * put the connection on a 'pending' queue and will assign it to
881 * a server when the config data arrives.
883 * Arguments:
884 * ls listening socket to accept from
886 * Returns:
887 * 0 success
888 * errno reason for failure
892 scsp_server_accept(int ls)
894 int len, rc, sd;
895 struct sockaddr server_addr;
896 Scsp_pending *psp;
899 * Accept the new connection
901 len = sizeof(server_addr);
902 sd = accept(ls, (struct sockaddr *)&server_addr, &len);
903 if (sd < 0) {
904 return(errno);
906 if (sd > scsp_max_socket) {
907 scsp_max_socket = sd;
911 * Set non-blocking operation
913 #ifdef sun
914 rc = fcntl(sd, F_SETFL, FNBIO + FNDELAY);
915 #else
916 rc = fcntl(sd, F_SETFL, O_NONBLOCK);
917 #endif
918 if (rc == -1) {
919 close(sd);
920 rc = errno;
924 * Put the new socket on the 'pending' queue
926 psp = (Scsp_pending *) UM_ALLOC(sizeof(Scsp_pending));
927 if (!psp) {
928 scsp_mem_err("scsp_server_accept: sizeof(Scsp_pending)");
930 psp->sp_sock = sd;
931 LINK2TAIL(psp, Scsp_pending, scsp_pending_head, sp_next);
933 return(0);
938 * Read a server interface message from a socket
940 * Arguments:
941 * sd socket to read from
943 * Returns:
944 * msg pointer to message read
945 * 0 failure (errno has reason)
948 Scsp_if_msg *
949 scsp_if_sock_read(int sd)
951 int len;
952 char *buff = NULL;
953 Scsp_if_msg *msg;
954 Scsp_if_msg_hdr msg_hdr;
957 * Read the message header from the socket
959 len = read(sd, (char *)&msg_hdr, sizeof(msg_hdr));
960 if (len != sizeof(msg_hdr)) {
961 if (len >= 0)
962 errno = EINVAL;
963 goto socket_read_fail;
967 * Get a buffer and read the rest of the message into it
969 buff = (char *)UM_ALLOC(msg_hdr.sh_len);
970 if (!buff) {
971 scsp_mem_err("scsp_if_sock_read: msg_hdr.sh_len");
973 msg = (Scsp_if_msg *)buff;
974 msg->si_hdr = msg_hdr;
975 len = read(sd, &buff[sizeof(Scsp_if_msg_hdr)],
976 msg->si_len - sizeof(Scsp_if_msg_hdr));
977 if (len != msg->si_len - sizeof(Scsp_if_msg_hdr)) {
978 if (len >= 0) {
979 errno = EINVAL;
981 goto socket_read_fail;
985 * Trace the message
987 if (scsp_trace_mode & SCSP_TRACE_IF_MSG) {
988 scsp_trace("Received server I/F message:\n");
989 print_scsp_if_msg(scsp_trace_file, msg);
990 scsp_trace("\n");
993 return(msg);
995 socket_read_fail:
996 if (buff)
997 UM_FREE(buff);
998 return(NULL);
1003 * Write a server interface message to a socket
1005 * Arguments:
1006 * sd socket to write to
1007 * msg pointer to message to write
1009 * Returns:
1010 * 0 success
1011 * errno reason for failure
1015 scsp_if_sock_write(int sd, Scsp_if_msg *msg)
1017 int len, rc;
1020 * Trace the message
1022 if (scsp_trace_mode & SCSP_TRACE_IF_MSG) {
1023 scsp_trace("Writing server I/F message:\n");
1024 print_scsp_if_msg(scsp_trace_file, msg);
1025 scsp_trace("\n");
1029 * Write the message to the indicated socket
1031 len = write(sd, (char *)msg, msg->si_len);
1032 if (len != msg->si_len) {
1033 if (len < 0)
1034 rc = errno;
1035 else
1036 rc = EINVAL;
1037 } else {
1038 rc = 0;
1041 return(rc);
1046 * Read data from a local server
1048 * Arguments:
1049 * ssp pointer to server block that has data
1051 * Returns:
1052 * 0 success
1053 * else errno indicating reason for failure
1057 scsp_server_read(Scsp_server *ssp)
1059 int rc;
1060 Scsp_dcs *dcsp;
1061 Scsp_if_msg *msg;
1064 * Read the message
1066 msg = scsp_if_sock_read(ssp->ss_sock);
1067 if (!msg) {
1068 if (errno == EWOULDBLOCK) {
1070 * Nothing to read--just return
1072 return(0);
1073 } else {
1075 * Error--shut down the server entry
1077 scsp_server_shutdown(ssp);
1079 return(errno);
1083 * Process the received message
1085 switch(msg->si_type) {
1086 case SCSP_NOP_REQ:
1088 * Ignore a NOP
1090 break;
1091 case SCSP_CACHE_RSP:
1093 * Summarize the server's cache and try to open
1094 * connections to all of its DCSs
1096 scsp_process_cache_rsp(ssp, msg);
1097 ssp->ss_state = SCSP_SS_ACTIVE;
1098 for (dcsp = ssp->ss_dcs; dcsp; dcsp = dcsp->sd_next) {
1099 if (scsp_dcs_connect(dcsp)) {
1101 * Connect failed -- the DCS may not
1102 * be up yet, so we'll try again later
1104 HARP_TIMER(&dcsp->sd_open_t,
1105 SCSP_Open_Interval,
1106 scsp_open_timeout);
1109 ssp->ss_state = SCSP_SS_ACTIVE;
1110 break;
1111 case SCSP_SOLICIT_RSP:
1113 * The server has answered our request for a particular
1114 * entry from its cache
1116 dcsp = (Scsp_dcs *)msg->si_tok;
1117 rc = scsp_cfsm(dcsp, SCSP_CIFSM_SOL_RSP, NULL, msg);
1118 break;
1119 case SCSP_UPDATE_REQ:
1121 * Pass the update request to the FSMs for all
1122 * DCSs associated with the server
1124 if (ssp->ss_state == SCSP_SS_ACTIVE) {
1125 for (dcsp = ssp->ss_dcs; dcsp;
1126 dcsp = dcsp->sd_next) {
1127 rc = scsp_cfsm(dcsp, SCSP_CIFSM_UPD_REQ,
1128 NULL, msg);
1131 break;
1132 case SCSP_UPDATE_RSP:
1134 * Pass the update response to the FSM for the
1135 * DCS associated with the request
1137 dcsp = (Scsp_dcs *)msg->si_tok;
1138 rc = scsp_cfsm(dcsp, SCSP_CIFSM_UPD_RSP, NULL, msg);
1139 break;
1140 default:
1141 scsp_log(LOG_ERR, "invalid message type %d from server",
1142 msg->si_type);
1143 return(EINVAL);
1146 UM_FREE(msg);
1147 return(0);
1152 * Send a Cache Indication to a server
1154 * Arguments:
1155 * ssp pointer to server block block
1157 * Returns:
1158 * 0 success
1159 * else errno indicating reason for failure
1163 scsp_send_cache_ind(Scsp_server *ssp)
1165 int rc;
1166 Scsp_if_msg *msg;
1169 * Get storage for a server interface message
1171 msg = (Scsp_if_msg *)UM_ALLOC(sizeof(Scsp_if_msg));
1172 if (!msg) {
1173 scsp_mem_err("scsp_send_cache_ind: sizeof(Scsp_if_msg)");
1175 UM_ZERO(msg, sizeof(Scsp_if_msg));
1178 * Fill out the message
1180 msg->si_type = SCSP_CACHE_IND;
1181 msg->si_rc = 0;
1182 msg->si_proto = ssp->ss_pid;
1183 msg->si_len = sizeof(Scsp_if_msg_hdr);
1184 msg->si_tok = (u_long)ssp;
1187 * Send the message
1189 rc = scsp_if_sock_write(ssp->ss_sock, msg);
1190 UM_FREE(msg);
1191 return(rc);
1196 * Read data from a pending server connection
1198 * Arguments:
1199 * psp pointer to pending block that has data
1201 * Returns:
1202 * 0 success
1203 * else errno indicating reason for failure
1207 scsp_pending_read(Scsp_pending *psp)
1209 int rc;
1210 Scsp_server *ssp;
1211 Scsp_if_msg *msg;
1214 * Read the message from the pending socket
1216 msg = scsp_if_sock_read(psp->sp_sock);
1217 if (!msg) {
1218 rc = errno;
1219 goto pending_read_fail;
1223 * Make sure this is configuration data
1225 if (msg->si_type != SCSP_CFG_REQ) {
1226 scsp_log(LOG_ERR, "invalid message type %d from pending server",
1227 msg->si_type);
1228 rc = EINVAL;
1229 goto pending_read_fail;
1233 * Find the server this message is for
1235 for (ssp = scsp_server_head; ssp; ssp = ssp->ss_next) {
1236 if (strcmp(ssp->ss_intf, msg->si_cfg.atmarp_netif) == 0)
1237 break;
1239 if (!ssp) {
1240 scsp_log(LOG_ERR, "refused connection from server for %s",
1241 msg->si_cfg.atmarp_netif);
1242 rc = EINVAL;
1243 goto config_reject;
1247 * Make sure the server is ready to go
1249 rc = scsp_get_server_info(ssp);
1250 if (rc) {
1251 goto config_reject;
1255 * Save the socket
1257 ssp->ss_sock = psp->sp_sock;
1258 ssp->ss_state = SCSP_SS_CFG;
1259 UNLINK(psp, Scsp_pending, scsp_pending_head, sp_next);
1260 UM_FREE(psp);
1263 * Listen for connections from the server's DCSs
1265 rc = scsp_dcs_listen(ssp);
1266 if (rc < 0) {
1267 rc = errno;
1268 goto config_reject;
1272 * Respond to the configuration message
1274 msg->si_type = SCSP_CFG_RSP;
1275 msg->si_rc = SCSP_RSP_OK;
1276 msg->si_len = sizeof(Scsp_if_msg_hdr);
1277 rc = scsp_if_sock_write(ssp->ss_sock, msg);
1278 if (rc) {
1279 goto config_error;
1283 * Ask the server to send us its cache
1285 rc = scsp_send_cache_ind(ssp);
1286 if (rc) {
1287 goto config_error;
1290 UM_FREE(msg);
1291 return(0);
1293 config_reject:
1295 * Respond to the configuration message
1297 msg->si_type = SCSP_CFG_RSP;
1298 msg->si_rc = SCSP_RSP_REJ;
1299 msg->si_len = sizeof(Scsp_if_msg_hdr);
1300 scsp_if_sock_write(ssp->ss_sock, msg);
1302 config_error:
1303 if (ssp->ss_sock != -1) {
1304 close(ssp->ss_sock);
1305 ssp->ss_sock = -1;
1307 if (ssp->ss_dcs_lsock != -1) {
1308 close(ssp->ss_dcs_lsock);
1309 ssp->ss_sock = -1;
1311 ssp->ss_state = SCSP_SS_NULL;
1312 UM_FREE(msg);
1314 return(rc);
1316 pending_read_fail:
1318 * Close the socket and free the pending read block
1320 close(psp->sp_sock);
1321 UNLINK(psp, Scsp_pending, scsp_pending_head, sp_next);
1322 UM_FREE(psp);
1323 if (msg)
1324 UM_FREE(msg);
1325 return(rc);