Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / usr.sbin / atm / scspd / scsp_socket.c
1 /*
2  *
3  * ===================================
4  * HARP  |  Host ATM Research Platform
5  * ===================================
6  *
7  *
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.
12  *
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.
20  *
21  * Copyright 1994-1998 Network Computing Services, Inc.
22  *
23  * Copies of this Software may be made, however, the above copyright
24  * notice must be reproduced on all copies.
25  *
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.2 2003/06/17 04:29:52 dillon Exp $
28  */
29
30
31 /*
32  * Server Cache Synchronization Protocol (SCSP) Support
33  * ----------------------------------------------------
34  *
35  * SCSP socket management routines
36  *
37  */
38
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>
51   
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>
60
61 #include "scsp_msg.h"
62 #include "scsp_if.h"
63 #include "scsp_var.h"
64
65 /*
66  * Local variables
67  */
68 static struct t_atm_llc llc_scsp = {
69         T_ATM_LLC_SHARING,
70         8,
71         {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x5e, 0x00, 0x05}
72 };
73
74 static struct t_atm_aal5        aal5 = {
75         0,                      /* forward_max_SDU_size */
76         0,                      /* backward_max_SDU_size */
77         0                       /* SSCS_type */
78 };
79
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 */
89         },
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 */
98         },
99         T_YES                   /* best_effort */
100 };
101
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 */
108 };
109
110 static struct t_atm_qos qos = {
111         T_ATM_NETWORK_CODING,           /* coding_standard */
112         {                               /* forward */
113                 T_ATM_QOS_CLASS_0       /* qos_class */
114         },
115         {                               /* backward */
116                 T_ATM_QOS_CLASS_0       /* qos_class */
117         }
118 };
119
120 static struct t_atm_app_name    appname = {
121         "SCSP"
122 };
123
124
125 /*
126  * Find a DCS, given its socket
127  *
128  * Arguments:
129  *      sd      socket descriptor
130  *
131  * Returns:
132  *      0       not found
133  *      address of DCS block corresponding to socket
134  *
135  */
136 Scsp_dcs *
137 scsp_find_dcs(sd)
138         int     sd;
139 {
140         Scsp_server     *ssp;
141         Scsp_dcs        *dcsp = NULL;
142
143         /*
144          * Loop through the list of servers
145          */
146         for (ssp = scsp_server_head; ssp; ssp = ssp->ss_next) {
147                 /*
148                  * Check all the DCSs chained from each server
149                  */
150                 for (dcsp = ssp->ss_dcs; dcsp; dcsp = dcsp->sd_next) {
151                         if (dcsp->sd_sock == sd)
152                                 break;
153                 }
154         }
155
156         return(dcsp);
157 }
158
159
160 /*
161  * Find a server, given its socket
162  *
163  * Arguments:
164  *      sd      socket descriptor
165  *
166  * Returns:
167  *      0       not found
168  *      address of server block corresponding to socket
169  *
170  */
171 Scsp_server *
172 scsp_find_server(sd)
173         int     sd;
174 {
175         Scsp_server     *ssp;
176
177         /*
178          * Loop through the list of servers
179          */
180         for (ssp = scsp_server_head; ssp; ssp = ssp->ss_next) {
181                 if (ssp->ss_sock == sd)
182                         break;
183         }
184
185         return(ssp);
186 }
187
188
189 /*
190  * Connect to a directly connected server
191  *
192  * Arguments:
193  *      dcsp    pointer to DCS block for server
194  *
195  * Returns:
196  *      0       success (dcsp->sd_sock is set)
197  *      else    errno indicating reason for failure
198  *
199  */
200 int
201 scsp_dcs_connect(dcsp)
202         Scsp_dcs        *dcsp;
203
204 {
205         int                     rc, sd;
206         struct sockaddr_atm     DCS_addr;
207
208         /*
209          * If the DCS already has an open connection, just return
210          */
211         if (dcsp->sd_sock != -1) {
212                 return(0);
213         }
214
215         /*
216          * Open an ATM socket
217          */
218         sd = socket(PF_ATM, SOCK_SEQPACKET, ATM_PROTO_AAL5);
219         if (sd == -1) {
220                 return(ESOCKTNOSUPPORT);
221         }
222         if (sd > scsp_max_socket) {
223                 scsp_max_socket = sd;
224         }
225
226         /*
227          * Set up connection parameters for SCSP connection
228          */
229         UM_ZERO(&DCS_addr, sizeof(DCS_addr));
230 #if (defined(BSD) && (BSD >= 199103))
231         DCS_addr.satm_len = sizeof(DCS_addr);
232 #endif
233         DCS_addr.satm_family = AF_ATM;
234         DCS_addr.satm_addr.t_atm_sap_addr.SVE_tag_addr =
235                         T_ATM_PRESENT;
236         DCS_addr.satm_addr.t_atm_sap_addr.SVE_tag_selector =
237                         T_ATM_PRESENT;
238         DCS_addr.satm_addr.t_atm_sap_addr.address_format =
239                         dcsp->sd_addr.address_format;
240         DCS_addr.satm_addr.t_atm_sap_addr.address_length =
241                         dcsp->sd_addr.address_length;
242         UM_COPY(dcsp->sd_addr.address,
243                         DCS_addr.satm_addr.t_atm_sap_addr.address,
244                         dcsp->sd_addr.address_length);
245
246         DCS_addr.satm_addr.t_atm_sap_layer2.SVE_tag =
247                         T_ATM_PRESENT;
248         DCS_addr.satm_addr.t_atm_sap_layer2.ID_type =
249                         T_ATM_SIMPLE_ID;
250         DCS_addr.satm_addr.t_atm_sap_layer2.ID.simple_ID =
251                         T_ATM_BLLI2_I8802;
252
253         DCS_addr.satm_addr.t_atm_sap_layer3.SVE_tag =
254                         T_ATM_ABSENT;
255         DCS_addr.satm_addr.t_atm_sap_appl.SVE_tag =
256                         T_ATM_ABSENT;
257
258         /*
259          * Bind the socket to our address
260          */
261         if (bind(sd, (struct sockaddr *)&DCS_addr,
262                         sizeof(DCS_addr))) {
263                 rc = errno;
264                 goto connect_fail;
265         }
266
267         /*
268          * Set non-blocking operation
269          */
270 #ifdef sun
271         rc = fcntl(sd, F_SETFL, FNBIO + FNDELAY);
272 #else
273         rc = fcntl(sd, F_SETFL, O_NONBLOCK);
274 #endif
275         if (rc == -1) {
276                 scsp_log(LOG_ERR, "scsp_dcs_connect: fcntl failed");
277                 rc = errno;
278                 goto connect_fail;
279         }
280
281         /*
282          * Set AAL 5 options
283          */
284         aal5.forward_max_SDU_size = dcsp->sd_server->ss_mtu;
285         aal5.backward_max_SDU_size = dcsp->sd_server->ss_mtu;
286         if (setsockopt(sd, T_ATM_SIGNALING, T_ATM_AAL5, (caddr_t)&aal5,
287                         sizeof(aal5)) < 0) {
288                 rc = EOPNOTSUPP;
289                 goto connect_fail;
290         }
291
292         /*
293          * Set traffic options
294          */
295         switch(dcsp->sd_server->ss_media) {
296         case MEDIA_TAXI_100:
297                 traffic.forward.PCR_all_traffic = ATM_PCR_TAXI100;
298                 traffic.backward.PCR_all_traffic = ATM_PCR_TAXI100;
299                 break;
300         case MEDIA_TAXI_140:
301                 traffic.forward.PCR_all_traffic = ATM_PCR_TAXI140;
302                 traffic.backward.PCR_all_traffic = ATM_PCR_TAXI140;
303                 break;
304         case MEDIA_OC3C:
305         case MEDIA_UTP155:
306                 traffic.forward.PCR_all_traffic = ATM_PCR_OC3C;
307                 traffic.backward.PCR_all_traffic = ATM_PCR_OC3C;
308                 break;
309         case MEDIA_OC12C:
310                 traffic.forward.PCR_all_traffic = ATM_PCR_OC12C;
311                 traffic.backward.PCR_all_traffic = ATM_PCR_OC12C;
312                 break;
313         case MEDIA_UNKNOWN:
314                 break;
315         }
316
317         if (setsockopt(sd, T_ATM_SIGNALING, T_ATM_TRAFFIC,
318                         (caddr_t)&traffic, sizeof(traffic)) < 0) {
319                 rc = EOPNOTSUPP;
320                 goto connect_fail;
321         }
322
323         /*
324          * Set bearer capability options
325          */
326         if (setsockopt(sd, T_ATM_SIGNALING, T_ATM_BEARER_CAP,
327                         (caddr_t)&bearer, sizeof(bearer)) < 0) {
328                 rc = EOPNOTSUPP;
329                 goto connect_fail;
330         }
331
332         /*
333          * Set QOS options
334          */
335         if (setsockopt(sd, T_ATM_SIGNALING, T_ATM_QOS,
336                         (caddr_t)&qos, sizeof(qos)) < 0) {
337                 rc = EOPNOTSUPP;
338                 goto connect_fail;
339         }
340
341         /*
342          * Set LLC identifier
343          */
344         if (setsockopt(sd, T_ATM_SIGNALING, T_ATM_LLC,
345                         (caddr_t)&llc_scsp, sizeof(llc_scsp)) < 0) {
346                 rc = EOPNOTSUPP;
347                 goto connect_fail;
348         }
349
350         /*
351          * Set application name
352          */
353         if (setsockopt(sd, T_ATM_SIGNALING, T_ATM_APP_NAME,
354                         (caddr_t)&appname, sizeof(appname)) < 0) {
355                 rc = EOPNOTSUPP;
356                 goto connect_fail;
357         }
358
359         /*
360          * Connect to DCS
361          */
362         if (connect(sd, (struct sockaddr *)&DCS_addr,
363                         sizeof(DCS_addr)) < 0 &&
364                         errno != EINPROGRESS) {
365                 rc = errno;
366                 goto connect_fail;
367         }
368
369         /*
370          * Set return values
371          */
372         dcsp->sd_sock = sd;
373         return(0);
374
375 connect_fail:
376         /*
377          * Close the socket if something didn't work
378          */
379         (void)close(sd);
380         dcsp->sd_sock = -1;
381         if (rc == 0)
382                 rc = EFAULT;
383         return(rc);
384 }
385
386
387 /*
388  * Listen for ATM connections from DCSs
389  *
390  * Arguments:
391  *      None
392  *
393  * Returns:
394  *      sock    socket which is listening (also set in
395                 ssp->ss_dcs_lsock)
396  *      -1      error encountered (reason in errno)
397  *
398  */
399 int
400 scsp_dcs_listen(ssp)
401         Scsp_server     *ssp;
402 {
403         int                     rc, sd;
404         struct sockaddr_atm     ls_addr;
405
406         /*
407          * Open a socket
408          */
409         sd = socket(PF_ATM, SOCK_SEQPACKET, ATM_PROTO_AAL5);
410         if (sd == -1) {
411                 rc = errno;
412                 goto listen_fail;
413         }
414         if (sd > scsp_max_socket) {
415                 scsp_max_socket = sd;
416         }
417
418         /*
419          * Set up our address
420          */
421         UM_ZERO(&ls_addr, sizeof(ls_addr));
422 #if (defined(BSD) && (BSD >= 199103))
423         ls_addr.satm_len = sizeof(ls_addr);
424 #endif
425         ls_addr.satm_family = AF_ATM;
426         ls_addr.satm_addr.t_atm_sap_addr.SVE_tag_addr = T_ATM_PRESENT;
427         ls_addr.satm_addr.t_atm_sap_addr.SVE_tag_selector =
428                         T_ATM_PRESENT;
429         ls_addr.satm_addr.t_atm_sap_addr.address_format =
430                         ssp->ss_addr.address_format;
431         ls_addr.satm_addr.t_atm_sap_addr.address_length =
432                         ssp->ss_addr.address_length;
433         UM_COPY(ssp->ss_addr.address,
434                         ls_addr.satm_addr.t_atm_sap_addr.address,
435                         ssp->ss_addr.address_length);
436
437         ls_addr.satm_addr.t_atm_sap_layer2.SVE_tag = T_ATM_PRESENT;
438         ls_addr.satm_addr.t_atm_sap_layer2.ID_type = T_ATM_SIMPLE_ID;
439         ls_addr.satm_addr.t_atm_sap_layer2.ID.simple_ID =
440                         T_ATM_BLLI2_I8802;
441
442         ls_addr.satm_addr.t_atm_sap_layer3.SVE_tag = T_ATM_ABSENT;
443         ls_addr.satm_addr.t_atm_sap_appl.SVE_tag = T_ATM_ABSENT;
444
445         /*
446          * Bind the socket to our address
447          */
448         rc = bind(sd, (struct sockaddr *)&ls_addr, sizeof(ls_addr));
449         if (rc == -1) {
450                 rc = errno;
451                 goto listen_fail;
452         }
453
454         /*
455          * Set non-blocking I/O
456          */
457 #ifdef sun
458         rc = fcntl(sd, F_SETFL, FNBIO + FNDELAY);
459 #else
460         rc = fcntl(sd, F_SETFL, O_NONBLOCK);
461 #endif
462         if (rc == -1) {
463                 scsp_log(LOG_ERR, "scsp_dcs_listen: fcntl failed");
464                 rc = errno;
465                 goto listen_fail;
466         }
467
468         /*
469          * Set AAL 5 options
470          */
471         aal5.forward_max_SDU_size = ssp->ss_mtu;
472         aal5.backward_max_SDU_size = ssp->ss_mtu;
473         if (setsockopt(sd, T_ATM_SIGNALING, T_ATM_AAL5, (caddr_t)&aal5,
474                         sizeof(aal5)) < 0) {
475                 rc = EOPNOTSUPP;
476                 goto listen_fail;
477         }
478
479         /*
480          * Set traffic options
481          */
482         switch(ssp->ss_media) {
483         case MEDIA_TAXI_100:
484                 traffic.forward.PCR_all_traffic = ATM_PCR_TAXI100;
485                 traffic.backward.PCR_all_traffic = ATM_PCR_TAXI100;
486                 break;
487         case MEDIA_TAXI_140:
488                 traffic.forward.PCR_all_traffic = ATM_PCR_TAXI140;
489                 traffic.backward.PCR_all_traffic = ATM_PCR_TAXI140;
490                 break;
491         case MEDIA_OC3C:
492         case MEDIA_UTP155:
493                 traffic.forward.PCR_all_traffic = ATM_PCR_OC3C;
494                 traffic.backward.PCR_all_traffic = ATM_PCR_OC3C;
495                 break;
496         case MEDIA_OC12C:
497                 traffic.forward.PCR_all_traffic = ATM_PCR_OC12C;
498                 traffic.backward.PCR_all_traffic = ATM_PCR_OC12C;
499                 break;
500         case MEDIA_UNKNOWN:
501                 break;
502         }
503
504         if (setsockopt(sd, T_ATM_SIGNALING, T_ATM_TRAFFIC,
505                         (caddr_t)&traffic, sizeof(traffic)) < 0) {
506                 rc = EOPNOTSUPP;
507                 goto listen_fail;
508         }
509
510         /*
511          * Set bearer capability options
512          */
513         if (setsockopt(sd, T_ATM_SIGNALING, T_ATM_BEARER_CAP,
514                         (caddr_t)&bearer, sizeof(bearer)) < 0) {
515                 rc = EOPNOTSUPP;
516                 goto listen_fail;
517         }
518
519         /*
520          * Set QOS options
521          */
522         if (setsockopt(sd, T_ATM_SIGNALING, T_ATM_QOS,
523                         (caddr_t)&qos, sizeof(qos)) < 0) {
524                 rc = EOPNOTSUPP;
525                 goto listen_fail;
526         }
527
528         /*
529          * Set LLC identifier
530          */
531         if (setsockopt(sd, T_ATM_SIGNALING, T_ATM_LLC,
532                         (caddr_t)&llc_scsp, sizeof(llc_scsp)) < 0) {
533                 rc = EOPNOTSUPP;
534                 goto listen_fail;
535         }
536
537         /*
538          * Set application name
539          */
540         if (setsockopt(sd, T_ATM_SIGNALING, T_ATM_APP_NAME,
541                         (caddr_t)&appname, sizeof(appname)) < 0) {
542                 rc = EOPNOTSUPP;
543                 goto listen_fail;
544         }
545
546         /*
547          * Listen for new connections
548          */
549         if (listen(sd, 5) < 0) {
550                 rc = errno;
551                 goto listen_fail;
552         }
553
554         ssp->ss_dcs_lsock = sd;
555         return(sd);
556
557 listen_fail:
558         /*
559          * Close the socket if anything didn't work
560          */
561         (void)close(sd);
562         if (rc == 0)
563                 errno = EFAULT;
564         else
565                 errno = rc;
566         ssp->ss_dcs_lsock = -1;
567         return(-1);
568 }
569
570
571 /*
572  * Accept a connection from a DCS
573  *
574  * Arguments:
575  *      ssp     pointer to server block
576  *
577  * Returns:
578  *      address of DCS with new connection
579  *      0       failure (errno has reason)
580  *
581  */
582 Scsp_dcs *
583 scsp_dcs_accept(ssp)
584         Scsp_server     *ssp;
585 {
586         int                     len, rc, sd;
587         struct sockaddr_atm     dcs_sockaddr;
588         struct t_atm_sap_addr   *dcs_addr = &dcs_sockaddr.satm_addr.t_atm_sap_addr;
589         Atm_addr                dcs_atmaddr;
590         Scsp_dcs                *dcsp;
591
592         /*
593          * Accept the new connection
594          */
595         len = sizeof(dcs_sockaddr);
596         sd = accept(ssp->ss_dcs_lsock,
597                         (struct sockaddr *)&dcs_sockaddr, &len);
598         if (sd < 0) {
599                 return((Scsp_dcs *)0);
600         }
601         if (sd > scsp_max_socket) {
602                 scsp_max_socket = sd;
603         }
604
605         /*
606          * Copy the DCS's address from the sockaddr to an Atm_addr
607          */
608         if (dcs_addr->SVE_tag_addr != T_ATM_PRESENT) {
609                 dcs_atmaddr.address_format = T_ATM_ABSENT;
610                 dcs_atmaddr.address_length = 0;
611         } else {
612                 dcs_atmaddr.address_format = dcs_addr->address_format;
613                 dcs_atmaddr.address_length = dcs_addr->address_length;
614                 UM_COPY(dcs_addr->address, dcs_atmaddr.address,
615                                 dcs_addr->address_length);
616         }
617
618         /*
619          * Find out which DCS this connection is for
620          */
621         for (dcsp = ssp->ss_dcs; dcsp; dcsp = dcsp->sd_next) {
622                 /*
623                  * Compare DCS's address to address
624                  * configured by user
625                  */
626                 if (ATM_ADDR_EQUAL(&dcsp->sd_addr,
627                                 &dcs_atmaddr))
628                         break;
629         }
630
631         /*
632          * Make sure we have this DCS configured
633          */
634         if (!dcsp) {
635                 errno = EINVAL;
636                 goto dcs_accept_fail;
637         }
638
639         /*
640          * Make sure we are in a state to accept the connection
641          */
642         if (ssp->ss_state != SCSP_SS_ACTIVE) {
643                 errno = EACCES;
644                 goto dcs_accept_fail;
645         }
646
647         /*
648          * Make sure we don't already have a connection to this DCS
649          */
650         if (dcsp->sd_sock != -1) {
651                 errno = EALREADY;
652                 goto dcs_accept_fail;
653         }
654
655         /*
656          * Set application name
657          */
658         if (setsockopt(sd, T_ATM_SIGNALING, T_ATM_APP_NAME,
659                         (caddr_t)&appname, sizeof(appname)) < 0) {
660                 rc = EOPNOTSUPP;
661                 goto dcs_accept_fail;
662         }
663
664         /*
665          * Set non-blocking I/O
666          */
667 #ifdef sun
668                 rc = fcntl(sd, F_SETFL, FNBIO + FNDELAY);
669 #else
670                 rc = fcntl(sd, F_SETFL, O_NONBLOCK);
671 #endif
672         if (rc == -1) {
673                 goto dcs_accept_fail;
674         }
675
676         /*
677          * Cancel the open retry timer
678          */
679         HARP_CANCEL(&dcsp->sd_open_t);
680
681         /*
682          * Save the socket address and return the
683          * address of the DCS
684          */
685         dcsp->sd_sock = sd;
686         return(dcsp);
687
688 dcs_accept_fail:
689         /*
690          * An error has occured--clean up and return
691          */
692         (void)close(sd);
693         return((Scsp_dcs *)0);
694 }
695
696
697 /*
698  * Read an SCSP message from a directly connected server
699  *
700  * Arguments:
701  *      dcsp    pointer to DCS block that has data
702  *
703  * Returns:
704  *      0       success
705  *      else    errno indicating reason for failure
706  *
707  */
708 int
709 scsp_dcs_read(dcsp)
710         Scsp_dcs        *dcsp;
711
712 {
713         int                     len, rc;
714         char                    *buff = (char *)0;
715         Scsp_server             *ssp = dcsp->sd_server;
716         Scsp_msg                *msg;
717
718         /*
719          * Get a buffer to hold the entire message
720          */
721         len = ssp->ss_mtu;
722         buff = (char *)UM_ALLOC(len);
723         if (!buff) {
724                 scsp_mem_err("scsp_dcs_read: ssp->ss_mtu");
725         }
726
727         /*
728          * Read the message
729          */
730         len = read(dcsp->sd_sock, buff, len);
731         if (len < 0) {
732                 goto dcs_read_fail;
733         }
734
735         /*
736          * Parse the input message and pass it to the Hello FSM
737          */
738         msg = scsp_parse_msg(buff, len);
739         if (msg) {
740                 /*
741                  * Write the message to the trace file if
742                  * it's of a type we're tracing
743                  */
744                 if (((scsp_trace_mode & SCSP_TRACE_HELLO_MSG) &&
745                                 msg->sc_msg_type == SCSP_HELLO_MSG) ||
746                                 ((scsp_trace_mode & SCSP_TRACE_CA_MSG) &&
747                                 msg->sc_msg_type != SCSP_HELLO_MSG)) {
748                         scsp_trace_msg(dcsp, msg, 1);
749                         scsp_trace("\n");
750                 }
751
752                 /*
753                  * Pass the message to the Hello FSM
754                  */
755                 rc = scsp_hfsm(dcsp, SCSP_HFSM_RCVD, msg);
756                 scsp_free_msg(msg);
757         } else {
758                 /*
759                  * Message was invalid.  Write it to the trace file
760                  * if we're tracing messages.
761                  */
762                 if (scsp_trace_mode & (SCSP_TRACE_HELLO_MSG &
763                                 SCSP_TRACE_CA_MSG)) {
764                         int     i;
765                         scsp_trace("Invalid message received:\n");
766                         scsp_trace("0x");
767                         for (i = 0; i < len; i++) {
768                                 scsp_trace("%02x ", (u_char)buff[i]);
769                         }
770                         scsp_trace("\n");
771                 }
772         }
773         UM_FREE(buff);
774
775         return(0);
776
777 dcs_read_fail:
778         /*
779          * Error on read--check for special conditions
780          */
781         rc = errno;
782         if (errno == ECONNRESET) {
783                 /*
784                  * VCC has been closed--pass the event to
785                  * the Hello FSM
786                  */
787                 rc = scsp_hfsm(dcsp, SCSP_HFSM_VC_CLOSED,
788                                 (Scsp_msg *)0);
789         }
790         if (errno == ECONNREFUSED) {
791                 /*
792                  * VCC open failed--set a timer and try
793                  * again when it fires
794                  */
795                 HARP_TIMER(&dcsp->sd_open_t,
796                                 SCSP_Open_Interval,
797                                 scsp_open_timeout);
798                 rc = 0;
799         }
800
801         if (buff)
802                 UM_FREE(buff);
803         return(rc);
804 }
805
806
807 /*
808  * Listen for Unix connections from SCSP client servers
809  *
810  * Arguments:
811  *      None
812  *
813  * Returns:
814  *      sock    socket which is listening
815  *      -1      error (reason in errno)
816  *
817  */
818 int
819 scsp_server_listen()
820 {
821         int     rc, sd;
822
823         static struct sockaddr  scsp_addr = {
824 #if (defined(BSD) && (BSD >= 199103))
825                 sizeof(struct sockaddr),        /* sa_len */
826 #endif
827                 AF_UNIX,                        /* sa_family */
828                 SCSPD_SOCK_NAME                 /* sa_data */
829         };
830
831         /*
832          * Unlink any old socket
833          */
834         rc = unlink(SCSPD_SOCK_NAME);
835         if (rc < 0 && errno != ENOENT)
836                 return(-1);
837
838         /*
839          * Open a socket
840          */
841         sd = socket(PF_UNIX, SOCK_STREAM, 0);
842         if (sd == -1) {
843                 return(-1);
844         }
845         if (sd > scsp_max_socket) {
846                 scsp_max_socket = sd;
847         }
848
849         /*
850          * Bind the socket's address
851          */
852         rc = bind(sd, &scsp_addr, sizeof(scsp_addr));
853         if (rc == -1) {
854                 (void)close(sd);
855                 return(-1);
856         }
857
858         /*
859          * Set non-blocking I/O
860          */
861 #ifdef sun
862                 rc = fcntl(sd, F_SETFL, FNBIO + FNDELAY);
863 #else
864                 rc = fcntl(sd, F_SETFL, O_NONBLOCK);
865 #endif
866         if (rc == -1) {
867                 (void)close(sd);
868                 return(-1);
869         }
870
871         /*
872          * Listen for new connections
873          */
874         if (listen(sd, 5) < 0) {
875                 (void)close(sd);
876                 return(-1);
877         }
878
879         return(sd);
880 }
881
882
883 /*
884  * Accept a connection from a server
885  *
886  * We accept a connection, but we won't know which server it is
887  * from until we get the configuration data from the server.  We
888  * put the connection on a 'pending' queue and will assign it to
889  * a server when the config data arrives.
890  *
891  * Arguments:
892  *      ls      listening socket to accept from
893  *
894  * Returns:
895  *      0       success
896  *      errno   reason for failure
897  *
898  */
899 int
900 scsp_server_accept(ls)
901         int     ls;
902
903 {
904         int             len, rc, sd;
905         struct sockaddr server_addr;
906         Scsp_pending    *psp;
907
908         /*
909          * Accept the new connection
910          */
911         len = sizeof(server_addr);
912         sd = accept(ls, (struct sockaddr *)&server_addr, &len);
913         if (sd < 0) {
914                 return(errno);
915         }
916         if (sd > scsp_max_socket) {
917                 scsp_max_socket = sd;
918         }
919
920         /*
921          * Set non-blocking operation
922          */
923 #ifdef sun
924         rc = fcntl(sd, F_SETFL, FNBIO + FNDELAY);
925 #else
926         rc = fcntl(sd, F_SETFL, O_NONBLOCK);
927 #endif
928         if (rc == -1) {
929                 (void)close(sd);
930                 rc = errno;
931         }
932
933         /*
934          * Put the new socket on the 'pending' queue
935          */
936         psp = (Scsp_pending *) UM_ALLOC(sizeof(Scsp_pending));
937         if (!psp) {
938                 scsp_mem_err("scsp_server_accept: sizeof(Scsp_pending)");
939         }
940         psp->sp_sock = sd;
941         LINK2TAIL(psp, Scsp_pending, scsp_pending_head, sp_next);
942
943         return(0);
944 }
945
946
947 /*
948  * Read a server interface message from a socket
949  *
950  * Arguments:
951  *      sd      socket to read from
952  *
953  * Returns:
954  *      msg     pointer to message read
955  *      0       failure (errno has reason)
956  *
957  */
958 Scsp_if_msg *
959 scsp_if_sock_read(sd)
960         int     sd;
961
962 {
963         int             len;
964         char            *buff = (char *)0;
965         Scsp_if_msg     *msg;
966         Scsp_if_msg_hdr msg_hdr;
967
968         /*
969          * Read the message header from the socket
970          */
971         len = read(sd, (char *)&msg_hdr, sizeof(msg_hdr));
972         if (len != sizeof(msg_hdr)) {
973                 if (len >= 0)
974                         errno = EINVAL;
975                 goto socket_read_fail;
976         }
977
978         /*
979          * Get a buffer and read the rest of the message into it
980          */
981         buff = (char *)UM_ALLOC(msg_hdr.sh_len);
982         if (!buff) {
983                 scsp_mem_err("scsp_if_sock_read: msg_hdr.sh_len");
984         }
985         msg = (Scsp_if_msg *)buff;
986         msg->si_hdr = msg_hdr;
987         len = read(sd, &buff[sizeof(Scsp_if_msg_hdr)],
988                         msg->si_len - sizeof(Scsp_if_msg_hdr));
989         if (len != msg->si_len - sizeof(Scsp_if_msg_hdr)) {
990                 if (len >= 0) {
991                         errno = EINVAL;
992                 }
993                 goto socket_read_fail;
994         }
995
996         /*
997          * Trace the message
998          */
999         if (scsp_trace_mode & SCSP_TRACE_IF_MSG) {
1000                 scsp_trace("Received server I/F message:\n");
1001                 print_scsp_if_msg(scsp_trace_file, msg);
1002                 scsp_trace("\n");
1003         }
1004
1005         return(msg);
1006
1007 socket_read_fail:
1008         if (buff)
1009                 UM_FREE(buff);
1010         return((Scsp_if_msg *)0);
1011 }
1012
1013
1014 /*
1015  * Write a server interface message to a socket
1016  *
1017  * Arguments:
1018  *      sd      socket to write to
1019  *      msg     pointer to message to write
1020  *
1021  * Returns:
1022  *      0       success
1023  *      errno   reason for failure
1024  *
1025  */
1026 int
1027 scsp_if_sock_write(sd, msg)
1028         int             sd;
1029         Scsp_if_msg     *msg;
1030 {
1031         int     len, rc;
1032
1033         /*
1034          * Trace the message
1035          */
1036         if (scsp_trace_mode & SCSP_TRACE_IF_MSG) {
1037                 scsp_trace("Writing server I/F message:\n");
1038                 print_scsp_if_msg(scsp_trace_file, msg);
1039                 scsp_trace("\n");
1040         }
1041
1042         /*
1043          * Write the message to the indicated socket
1044          */
1045         len = write(sd, (char *)msg, msg->si_len);
1046         if (len != msg->si_len) {
1047                 if (len < 0)
1048                         rc = errno;
1049                 else
1050                         rc = EINVAL;
1051         } else {
1052                 rc = 0;
1053         }
1054
1055         return(rc);
1056 }
1057
1058
1059 /*
1060  * Read data from a local server
1061  *
1062  * Arguments:
1063  *      ssp     pointer to server block that has data
1064  *
1065  * Returns:
1066  *      0       success
1067  *      else    errno indicating reason for failure
1068  *
1069  */
1070 int
1071 scsp_server_read(ssp)
1072         Scsp_server     *ssp;
1073 {
1074         int             rc;
1075         Scsp_dcs        *dcsp;
1076         Scsp_if_msg     *msg;
1077
1078         /*
1079          * Read the message
1080          */
1081         msg = scsp_if_sock_read(ssp->ss_sock);
1082         if (!msg) {
1083                 if (errno == EWOULDBLOCK) {
1084                         /*
1085                          * Nothing to read--just return
1086                          */
1087                         return(0);
1088                 } else {
1089                         /*
1090                          * Error--shut down the server entry
1091                          */
1092                         scsp_server_shutdown(ssp);
1093                 }
1094                 return(errno);
1095         }
1096
1097         /*
1098          * Process the received message
1099          */
1100         switch(msg->si_type) {
1101         case SCSP_NOP_REQ:
1102                 /*
1103                  * Ignore a NOP
1104                  */
1105                 break;
1106         case SCSP_CACHE_RSP:
1107                 /*
1108                  * Summarize the server's cache and try to open
1109                  * connections to all of its DCSs
1110                  */
1111                 scsp_process_cache_rsp(ssp, msg);
1112                 ssp->ss_state = SCSP_SS_ACTIVE;
1113                 for (dcsp = ssp->ss_dcs; dcsp; dcsp = dcsp->sd_next) {
1114                         if (scsp_dcs_connect(dcsp)) {
1115                                 /*
1116                                  * Connect failed -- the DCS may not
1117                                  * be up yet, so we'll try again later
1118                                  */
1119                                 HARP_TIMER(&dcsp->sd_open_t,
1120                                                 SCSP_Open_Interval,
1121                                                 scsp_open_timeout);
1122                         }
1123                 }
1124                 ssp->ss_state = SCSP_SS_ACTIVE;
1125                 break;
1126         case SCSP_SOLICIT_RSP:
1127                 /*
1128                  * The server has answered our request for a particular
1129                  * entry from its cache
1130                  */
1131                 dcsp = (Scsp_dcs *)msg->si_tok;
1132                 rc = scsp_cfsm(dcsp, SCSP_CIFSM_SOL_RSP, (Scsp_msg *)0,
1133                                 msg);
1134                 break;
1135         case SCSP_UPDATE_REQ:
1136                 /*
1137                  * Pass the update request to the FSMs for all
1138                  * DCSs associated with the server
1139                  */
1140                 if (ssp->ss_state == SCSP_SS_ACTIVE) {
1141                         for (dcsp = ssp->ss_dcs; dcsp;
1142                                         dcsp = dcsp->sd_next) {
1143                                 rc = scsp_cfsm(dcsp, SCSP_CIFSM_UPD_REQ,
1144                                                 (Scsp_msg *)0, msg);
1145                         }
1146                 }
1147                 break;
1148         case SCSP_UPDATE_RSP:
1149                 /*
1150                  * Pass the update response to the FSM for the
1151                  * DCS associated with the request
1152                  */
1153                 dcsp = (Scsp_dcs *)msg->si_tok;
1154                 rc = scsp_cfsm(dcsp, SCSP_CIFSM_UPD_RSP,
1155                                 (Scsp_msg *)0, msg);
1156                 break;
1157         default:
1158                 scsp_log(LOG_ERR, "invalid message type %d from server",
1159                                 msg->si_type);
1160                 return(EINVAL);
1161         }
1162
1163         UM_FREE(msg);
1164         return(0);
1165 }
1166
1167
1168 /*
1169  * Send a Cache Indication to a server
1170  *
1171  * Arguments:
1172  *      ssp     pointer to server block block
1173  *
1174  * Returns:
1175  *      0       success
1176  *      else    errno indicating reason for failure
1177  *
1178  */
1179 int
1180 scsp_send_cache_ind(ssp)
1181         Scsp_server     *ssp;
1182 {
1183         int             rc;
1184         Scsp_if_msg     *msg;
1185
1186         /*
1187          * Get storage for a server interface message
1188          */
1189         msg = (Scsp_if_msg *)UM_ALLOC(sizeof(Scsp_if_msg));
1190         if (!msg) {
1191                 scsp_mem_err("scsp_send_cache_ind: sizeof(Scsp_if_msg)");
1192         }
1193         UM_ZERO(msg, sizeof(Scsp_if_msg));
1194
1195         /*
1196          * Fill out the message
1197          */
1198         msg->si_type = SCSP_CACHE_IND;
1199         msg->si_rc = 0;
1200         msg->si_proto = ssp->ss_pid;
1201         msg->si_len = sizeof(Scsp_if_msg_hdr);
1202         msg->si_tok = (u_long)ssp;
1203
1204         /*
1205          * Send the message
1206          */
1207         rc = scsp_if_sock_write(ssp->ss_sock, msg);
1208         UM_FREE(msg);
1209         return(rc);
1210 }
1211
1212
1213 /*
1214  * Read data from a pending server connection
1215  *
1216  * Arguments:
1217  *      psp     pointer to pending block that has data
1218  *
1219  * Returns:
1220  *      0       success
1221  *      else    errno indicating reason for failure
1222  *
1223  */
1224 int
1225 scsp_pending_read(psp)
1226         Scsp_pending    *psp;
1227
1228 {
1229         int             rc;
1230         Scsp_server     *ssp;
1231         Scsp_if_msg     *msg;
1232
1233         /*
1234          * Read the message from the pending socket
1235          */
1236         msg = scsp_if_sock_read(psp->sp_sock);
1237         if (!msg) {
1238                 rc = errno;
1239                 goto pending_read_fail;
1240         }
1241
1242         /*
1243          * Make sure this is configuration data
1244          */
1245         if (msg->si_type != SCSP_CFG_REQ) {
1246                 scsp_log(LOG_ERR, "invalid message type %d from pending server",
1247                                 msg->si_type);
1248                 rc = EINVAL;
1249                 goto pending_read_fail;
1250         }
1251
1252         /*
1253          * Find the server this message is for
1254          */
1255         for (ssp = scsp_server_head; ssp; ssp = ssp->ss_next) {
1256                 if (strcmp(ssp->ss_intf, msg->si_cfg.atmarp_netif) == 0)
1257                         break;
1258         }
1259         if (!ssp) {
1260                 scsp_log(LOG_ERR, "refused connection from server for %s",
1261                                 msg->si_cfg.atmarp_netif);
1262                 rc = EINVAL;
1263                 goto config_reject;
1264         }
1265
1266         /*
1267          * Make sure the server is ready to go
1268          */
1269         rc = scsp_get_server_info(ssp);
1270         if (rc) {
1271                 goto config_reject;
1272         }
1273
1274         /*
1275          * Save the socket
1276          */
1277         ssp->ss_sock = psp->sp_sock;
1278         ssp->ss_state = SCSP_SS_CFG;
1279         UNLINK(psp, Scsp_pending, scsp_pending_head, sp_next);
1280         UM_FREE(psp);
1281
1282         /*
1283          * Listen for connections from the server's DCSs
1284          */
1285         rc = scsp_dcs_listen(ssp);
1286         if (rc < 0) {
1287                 rc = errno;
1288                 goto config_reject;
1289         }
1290
1291         /*
1292          * Respond to the configuration message
1293          */
1294         msg->si_type = SCSP_CFG_RSP;
1295         msg->si_rc = SCSP_RSP_OK;
1296         msg->si_len = sizeof(Scsp_if_msg_hdr);
1297         rc = scsp_if_sock_write(ssp->ss_sock, msg);
1298         if (rc) {
1299                 goto config_error;;
1300         }
1301
1302         /*
1303          * Ask the server to send us its cache
1304          */
1305         rc = scsp_send_cache_ind(ssp);
1306         if (rc) {
1307                 goto config_error;
1308         }
1309
1310         UM_FREE(msg);
1311         return(0);
1312
1313 config_reject:
1314         /*
1315          * Respond to the configuration message
1316          */
1317         msg->si_type = SCSP_CFG_RSP;
1318         msg->si_rc = SCSP_RSP_REJ;
1319         msg->si_len = sizeof(Scsp_if_msg_hdr);
1320         (void)scsp_if_sock_write(ssp->ss_sock, msg);
1321
1322 config_error:
1323         if (ssp->ss_sock != -1) {
1324                 (void)close(ssp->ss_sock);
1325                 ssp->ss_sock = -1;
1326         }
1327         if (ssp->ss_dcs_lsock != -1) {
1328                 (void)close(ssp->ss_dcs_lsock);
1329                 ssp->ss_sock = -1;
1330         }
1331         ssp->ss_state = SCSP_SS_NULL;
1332         UM_FREE(msg);
1333
1334         return(rc);
1335
1336 pending_read_fail:
1337         /*
1338          * Close the socket and free the pending read block
1339          */
1340         (void)close(psp->sp_sock);
1341         UNLINK(psp, Scsp_pending, scsp_pending_head, sp_next);
1342         UM_FREE(psp);
1343         if (msg)
1344                 UM_FREE(msg);
1345         return(rc);
1346 }