6b882c0d1142f9b4cbe9484ab73646f94cfaad1d
[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.4 2004/12/18 22:48:02 swildner 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(int sd)
138 {
139         Scsp_server     *ssp;
140         Scsp_dcs        *dcsp = NULL;
141
142         /*
143          * Loop through the list of servers
144          */
145         for (ssp = scsp_server_head; ssp; ssp = ssp->ss_next) {
146                 /*
147                  * Check all the DCSs chained from each server
148                  */
149                 for (dcsp = ssp->ss_dcs; dcsp; dcsp = dcsp->sd_next) {
150                         if (dcsp->sd_sock == sd)
151                                 break;
152                 }
153         }
154
155         return(dcsp);
156 }
157
158
159 /*
160  * Find a server, given its socket
161  *
162  * Arguments:
163  *      sd      socket descriptor
164  *
165  * Returns:
166  *      0       not found
167  *      address of server block corresponding to socket
168  *
169  */
170 Scsp_server *
171 scsp_find_server(int sd)
172 {
173         Scsp_server     *ssp;
174
175         /*
176          * Loop through the list of servers
177          */
178         for (ssp = scsp_server_head; ssp; ssp = ssp->ss_next) {
179                 if (ssp->ss_sock == sd)
180                         break;
181         }
182
183         return(ssp);
184 }
185
186
187 /*
188  * Connect to a directly connected server
189  *
190  * Arguments:
191  *      dcsp    pointer to DCS block for server
192  *
193  * Returns:
194  *      0       success (dcsp->sd_sock is set)
195  *      else    errno indicating reason for failure
196  *
197  */
198 int
199 scsp_dcs_connect(Scsp_dcs *dcsp)
200
201 {
202         int                     rc, sd;
203         struct sockaddr_atm     DCS_addr;
204
205         /*
206          * If the DCS already has an open connection, just return
207          */
208         if (dcsp->sd_sock != -1) {
209                 return(0);
210         }
211
212         /*
213          * Open an ATM socket
214          */
215         sd = socket(PF_ATM, SOCK_SEQPACKET, ATM_PROTO_AAL5);
216         if (sd == -1) {
217                 return(ESOCKTNOSUPPORT);
218         }
219         if (sd > scsp_max_socket) {
220                 scsp_max_socket = sd;
221         }
222
223         /*
224          * Set up connection parameters for SCSP connection
225          */
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);
242
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;
249
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;
254
255         /*
256          * Bind the socket to our address
257          */
258         if (bind(sd, (struct sockaddr *)&DCS_addr,
259                         sizeof(DCS_addr))) {
260                 rc = errno;
261                 goto connect_fail;
262         }
263
264         /*
265          * Set non-blocking operation
266          */
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;
276         }
277
278         /*
279          * Set AAL 5 options
280          */
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;
287         }
288
289         /*
290          * Set traffic options
291          */
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;
312         }
313
314         if (setsockopt(sd, T_ATM_SIGNALING, T_ATM_TRAFFIC,
315                         (caddr_t)&traffic, sizeof(traffic)) < 0) {
316                 rc = EOPNOTSUPP;
317                 goto connect_fail;
318         }
319
320         /*
321          * Set bearer capability options
322          */
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;
327         }
328
329         /*
330          * Set QOS options
331          */
332         if (setsockopt(sd, T_ATM_SIGNALING, T_ATM_QOS,
333                         (caddr_t)&qos, sizeof(qos)) < 0) {
334                 rc = EOPNOTSUPP;
335                 goto connect_fail;
336         }
337
338         /*
339          * Set LLC identifier
340          */
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;
345         }
346
347         /*
348          * Set application name
349          */
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;
354         }
355
356         /*
357          * Connect to DCS
358          */
359         if (connect(sd, (struct sockaddr *)&DCS_addr,
360                         sizeof(DCS_addr)) < 0 &&
361                         errno != EINPROGRESS) {
362                 rc = errno;
363                 goto connect_fail;
364         }
365
366         /*
367          * Set return values
368          */
369         dcsp->sd_sock = sd;
370         return(0);
371
372 connect_fail:
373         /*
374          * Close the socket if something didn't work
375          */
376         close(sd);
377         dcsp->sd_sock = -1;
378         if (rc == 0)
379                 rc = EFAULT;
380         return(rc);
381 }
382
383
384 /*
385  * Listen for ATM connections from DCSs
386  *
387  * Arguments:
388  *      None
389  *
390  * Returns:
391  *      sock    socket which is listening (also set in
392                 ssp->ss_dcs_lsock)
393  *      -1      error encountered (reason in errno)
394  *
395  */
396 int
397 scsp_dcs_listen(Scsp_server *ssp)
398 {
399         int                     rc, sd;
400         struct sockaddr_atm     ls_addr;
401
402         /*
403          * Open a socket
404          */
405         sd = socket(PF_ATM, SOCK_SEQPACKET, ATM_PROTO_AAL5);
406         if (sd == -1) {
407                 rc = errno;
408                 goto listen_fail;
409         }
410         if (sd > scsp_max_socket) {
411                 scsp_max_socket = sd;
412         }
413
414         /*
415          * Set up our address
416          */
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);
432
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;
437
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;
440
441         /*
442          * Bind the socket to our address
443          */
444         rc = bind(sd, (struct sockaddr *)&ls_addr, sizeof(ls_addr));
445         if (rc == -1) {
446                 rc = errno;
447                 goto listen_fail;
448         }
449
450         /*
451          * Set non-blocking I/O
452          */
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;
462         }
463
464         /*
465          * Set AAL 5 options
466          */
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;
473         }
474
475         /*
476          * Set traffic options
477          */
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;
498         }
499
500         if (setsockopt(sd, T_ATM_SIGNALING, T_ATM_TRAFFIC,
501                         (caddr_t)&traffic, sizeof(traffic)) < 0) {
502                 rc = EOPNOTSUPP;
503                 goto listen_fail;
504         }
505
506         /*
507          * Set bearer capability options
508          */
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;
513         }
514
515         /*
516          * Set QOS options
517          */
518         if (setsockopt(sd, T_ATM_SIGNALING, T_ATM_QOS,
519                         (caddr_t)&qos, sizeof(qos)) < 0) {
520                 rc = EOPNOTSUPP;
521                 goto listen_fail;
522         }
523
524         /*
525          * Set LLC identifier
526          */
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;
531         }
532
533         /*
534          * Set application name
535          */
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;
540         }
541
542         /*
543          * Listen for new connections
544          */
545         if (listen(sd, 5) < 0) {
546                 rc = errno;
547                 goto listen_fail;
548         }
549
550         ssp->ss_dcs_lsock = sd;
551         return(sd);
552
553 listen_fail:
554         /*
555          * Close the socket if anything didn't work
556          */
557         close(sd);
558         if (rc == 0)
559                 errno = EFAULT;
560         else
561                 errno = rc;
562         ssp->ss_dcs_lsock = -1;
563         return(-1);
564 }
565
566
567 /*
568  * Accept a connection from a DCS
569  *
570  * Arguments:
571  *      ssp     pointer to server block
572  *
573  * Returns:
574  *      address of DCS with new connection
575  *      0       failure (errno has reason)
576  *
577  */
578 Scsp_dcs *
579 scsp_dcs_accept(Scsp_server *ssp)
580 {
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;
586
587         /*
588          * Accept the new connection
589          */
590         len = sizeof(dcs_sockaddr);
591         sd = accept(ssp->ss_dcs_lsock,
592                         (struct sockaddr *)&dcs_sockaddr, &len);
593         if (sd < 0) {
594                 return((Scsp_dcs *)0);
595         }
596         if (sd > scsp_max_socket) {
597                 scsp_max_socket = sd;
598         }
599
600         /*
601          * Copy the DCS's address from the sockaddr to an Atm_addr
602          */
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);
611         }
612
613         /*
614          * Find out which DCS this connection is for
615          */
616         for (dcsp = ssp->ss_dcs; dcsp; dcsp = dcsp->sd_next) {
617                 /*
618                  * Compare DCS's address to address
619                  * configured by user
620                  */
621                 if (ATM_ADDR_EQUAL(&dcsp->sd_addr,
622                                 &dcs_atmaddr))
623                         break;
624         }
625
626         /*
627          * Make sure we have this DCS configured
628          */
629         if (!dcsp) {
630                 errno = EINVAL;
631                 goto dcs_accept_fail;
632         }
633
634         /*
635          * Make sure we are in a state to accept the connection
636          */
637         if (ssp->ss_state != SCSP_SS_ACTIVE) {
638                 errno = EACCES;
639                 goto dcs_accept_fail;
640         }
641
642         /*
643          * Make sure we don't already have a connection to this DCS
644          */
645         if (dcsp->sd_sock != -1) {
646                 errno = EALREADY;
647                 goto dcs_accept_fail;
648         }
649
650         /*
651          * Set application name
652          */
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;
657         }
658
659         /*
660          * Set non-blocking I/O
661          */
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;
669         }
670
671         /*
672          * Cancel the open retry timer
673          */
674         HARP_CANCEL(&dcsp->sd_open_t);
675
676         /*
677          * Save the socket address and return the
678          * address of the DCS
679          */
680         dcsp->sd_sock = sd;
681         return(dcsp);
682
683 dcs_accept_fail:
684         /*
685          * An error has occured--clean up and return
686          */
687         close(sd);
688         return((Scsp_dcs *)0);
689 }
690
691
692 /*
693  * Read an SCSP message from a directly connected server
694  *
695  * Arguments:
696  *      dcsp    pointer to DCS block that has data
697  *
698  * Returns:
699  *      0       success
700  *      else    errno indicating reason for failure
701  *
702  */
703 int
704 scsp_dcs_read(Scsp_dcs *dcsp)
705 {
706         int                     len, rc;
707         char                    *buff = (char *)0;
708         Scsp_server             *ssp = dcsp->sd_server;
709         Scsp_msg                *msg;
710
711         /*
712          * Get a buffer to hold the entire message
713          */
714         len = ssp->ss_mtu;
715         buff = (char *)UM_ALLOC(len);
716         if (!buff) {
717                 scsp_mem_err("scsp_dcs_read: ssp->ss_mtu");
718         }
719
720         /*
721          * Read the message
722          */
723         len = read(dcsp->sd_sock, buff, len);
724         if (len < 0) {
725                 goto dcs_read_fail;
726         }
727
728         /*
729          * Parse the input message and pass it to the Hello FSM
730          */
731         msg = scsp_parse_msg(buff, len);
732         if (msg) {
733                 /*
734                  * Write the message to the trace file if
735                  * it's of a type we're tracing
736                  */
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");
743                 }
744
745                 /*
746                  * Pass the message to the Hello FSM
747                  */
748                 rc = scsp_hfsm(dcsp, SCSP_HFSM_RCVD, msg);
749                 scsp_free_msg(msg);
750         } else {
751                 /*
752                  * Message was invalid.  Write it to the trace file
753                  * if we're tracing messages.
754                  */
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]);
762                         }
763                         scsp_trace("\n");
764                 }
765         }
766         UM_FREE(buff);
767
768         return(0);
769
770 dcs_read_fail:
771         /*
772          * Error on read--check for special conditions
773          */
774         rc = errno;
775         if (errno == ECONNRESET) {
776                 /*
777                  * VCC has been closed--pass the event to
778                  * the Hello FSM
779                  */
780                 rc = scsp_hfsm(dcsp, SCSP_HFSM_VC_CLOSED,
781                                 (Scsp_msg *)0);
782         }
783         if (errno == ECONNREFUSED) {
784                 /*
785                  * VCC open failed--set a timer and try
786                  * again when it fires
787                  */
788                 HARP_TIMER(&dcsp->sd_open_t,
789                                 SCSP_Open_Interval,
790                                 scsp_open_timeout);
791                 rc = 0;
792         }
793
794         if (buff)
795                 UM_FREE(buff);
796         return(rc);
797 }
798
799
800 /*
801  * Listen for Unix connections from SCSP client servers
802  *
803  * Arguments:
804  *      None
805  *
806  * Returns:
807  *      sock    socket which is listening
808  *      -1      error (reason in errno)
809  *
810  */
811 int
812 scsp_server_listen(void)
813 {
814         int     rc, sd;
815
816         static struct sockaddr  scsp_addr = {
817 #if (defined(BSD) && (BSD >= 199103))
818                 sizeof(struct sockaddr),        /* sa_len */
819 #endif
820                 AF_UNIX,                        /* sa_family */
821                 SCSPD_SOCK_NAME                 /* sa_data */
822         };
823
824         /*
825          * Unlink any old socket
826          */
827         rc = unlink(SCSPD_SOCK_NAME);
828         if (rc < 0 && errno != ENOENT)
829                 return(-1);
830
831         /*
832          * Open a socket
833          */
834         sd = socket(PF_UNIX, SOCK_STREAM, 0);
835         if (sd == -1) {
836                 return(-1);
837         }
838         if (sd > scsp_max_socket) {
839                 scsp_max_socket = sd;
840         }
841
842         /*
843          * Bind the socket's address
844          */
845         rc = bind(sd, &scsp_addr, sizeof(scsp_addr));
846         if (rc == -1) {
847                 close(sd);
848                 return(-1);
849         }
850
851         /*
852          * Set non-blocking I/O
853          */
854 #ifdef sun
855                 rc = fcntl(sd, F_SETFL, FNBIO + FNDELAY);
856 #else
857                 rc = fcntl(sd, F_SETFL, O_NONBLOCK);
858 #endif
859         if (rc == -1) {
860                 close(sd);
861                 return(-1);
862         }
863
864         /*
865          * Listen for new connections
866          */
867         if (listen(sd, 5) < 0) {
868                 close(sd);
869                 return(-1);
870         }
871
872         return(sd);
873 }
874
875
876 /*
877  * Accept a connection from a server
878  *
879  * We accept a connection, but we won't know which server it is
880  * from until we get the configuration data from the server.  We
881  * put the connection on a 'pending' queue and will assign it to
882  * a server when the config data arrives.
883  *
884  * Arguments:
885  *      ls      listening socket to accept from
886  *
887  * Returns:
888  *      0       success
889  *      errno   reason for failure
890  *
891  */
892 int
893 scsp_server_accept(int ls)
894 {
895         int             len, rc, sd;
896         struct sockaddr server_addr;
897         Scsp_pending    *psp;
898
899         /*
900          * Accept the new connection
901          */
902         len = sizeof(server_addr);
903         sd = accept(ls, (struct sockaddr *)&server_addr, &len);
904         if (sd < 0) {
905                 return(errno);
906         }
907         if (sd > scsp_max_socket) {
908                 scsp_max_socket = sd;
909         }
910
911         /*
912          * Set non-blocking operation
913          */
914 #ifdef sun
915         rc = fcntl(sd, F_SETFL, FNBIO + FNDELAY);
916 #else
917         rc = fcntl(sd, F_SETFL, O_NONBLOCK);
918 #endif
919         if (rc == -1) {
920                 close(sd);
921                 rc = errno;
922         }
923
924         /*
925          * Put the new socket on the 'pending' queue
926          */
927         psp = (Scsp_pending *) UM_ALLOC(sizeof(Scsp_pending));
928         if (!psp) {
929                 scsp_mem_err("scsp_server_accept: sizeof(Scsp_pending)");
930         }
931         psp->sp_sock = sd;
932         LINK2TAIL(psp, Scsp_pending, scsp_pending_head, sp_next);
933
934         return(0);
935 }
936
937
938 /*
939  * Read a server interface message from a socket
940  *
941  * Arguments:
942  *      sd      socket to read from
943  *
944  * Returns:
945  *      msg     pointer to message read
946  *      0       failure (errno has reason)
947  *
948  */
949 Scsp_if_msg *
950 scsp_if_sock_read(int sd)
951 {
952         int             len;
953         char            *buff = (char *)0;
954         Scsp_if_msg     *msg;
955         Scsp_if_msg_hdr msg_hdr;
956
957         /*
958          * Read the message header from the socket
959          */
960         len = read(sd, (char *)&msg_hdr, sizeof(msg_hdr));
961         if (len != sizeof(msg_hdr)) {
962                 if (len >= 0)
963                         errno = EINVAL;
964                 goto socket_read_fail;
965         }
966
967         /*
968          * Get a buffer and read the rest of the message into it
969          */
970         buff = (char *)UM_ALLOC(msg_hdr.sh_len);
971         if (!buff) {
972                 scsp_mem_err("scsp_if_sock_read: msg_hdr.sh_len");
973         }
974         msg = (Scsp_if_msg *)buff;
975         msg->si_hdr = msg_hdr;
976         len = read(sd, &buff[sizeof(Scsp_if_msg_hdr)],
977                         msg->si_len - sizeof(Scsp_if_msg_hdr));
978         if (len != msg->si_len - sizeof(Scsp_if_msg_hdr)) {
979                 if (len >= 0) {
980                         errno = EINVAL;
981                 }
982                 goto socket_read_fail;
983         }
984
985         /*
986          * Trace the message
987          */
988         if (scsp_trace_mode & SCSP_TRACE_IF_MSG) {
989                 scsp_trace("Received server I/F message:\n");
990                 print_scsp_if_msg(scsp_trace_file, msg);
991                 scsp_trace("\n");
992         }
993
994         return(msg);
995
996 socket_read_fail:
997         if (buff)
998                 UM_FREE(buff);
999         return((Scsp_if_msg *)0);
1000 }
1001
1002
1003 /*
1004  * Write a server interface message to a socket
1005  *
1006  * Arguments:
1007  *      sd      socket to write to
1008  *      msg     pointer to message to write
1009  *
1010  * Returns:
1011  *      0       success
1012  *      errno   reason for failure
1013  *
1014  */
1015 int
1016 scsp_if_sock_write(int sd, Scsp_if_msg *msg)
1017 {
1018         int     len, rc;
1019
1020         /*
1021          * Trace the message
1022          */
1023         if (scsp_trace_mode & SCSP_TRACE_IF_MSG) {
1024                 scsp_trace("Writing server I/F message:\n");
1025                 print_scsp_if_msg(scsp_trace_file, msg);
1026                 scsp_trace("\n");
1027         }
1028
1029         /*
1030          * Write the message to the indicated socket
1031          */
1032         len = write(sd, (char *)msg, msg->si_len);
1033         if (len != msg->si_len) {
1034                 if (len < 0)
1035                         rc = errno;
1036                 else
1037                         rc = EINVAL;
1038         } else {
1039                 rc = 0;
1040         }
1041
1042         return(rc);
1043 }
1044
1045
1046 /*
1047  * Read data from a local server
1048  *
1049  * Arguments:
1050  *      ssp     pointer to server block that has data
1051  *
1052  * Returns:
1053  *      0       success
1054  *      else    errno indicating reason for failure
1055  *
1056  */
1057 int
1058 scsp_server_read(Scsp_server *ssp)
1059 {
1060         int             rc;
1061         Scsp_dcs        *dcsp;
1062         Scsp_if_msg     *msg;
1063
1064         /*
1065          * Read the message
1066          */
1067         msg = scsp_if_sock_read(ssp->ss_sock);
1068         if (!msg) {
1069                 if (errno == EWOULDBLOCK) {
1070                         /*
1071                          * Nothing to read--just return
1072                          */
1073                         return(0);
1074                 } else {
1075                         /*
1076                          * Error--shut down the server entry
1077                          */
1078                         scsp_server_shutdown(ssp);
1079                 }
1080                 return(errno);
1081         }
1082
1083         /*
1084          * Process the received message
1085          */
1086         switch(msg->si_type) {
1087         case SCSP_NOP_REQ:
1088                 /*
1089                  * Ignore a NOP
1090                  */
1091                 break;
1092         case SCSP_CACHE_RSP:
1093                 /*
1094                  * Summarize the server's cache and try to open
1095                  * connections to all of its DCSs
1096                  */
1097                 scsp_process_cache_rsp(ssp, msg);
1098                 ssp->ss_state = SCSP_SS_ACTIVE;
1099                 for (dcsp = ssp->ss_dcs; dcsp; dcsp = dcsp->sd_next) {
1100                         if (scsp_dcs_connect(dcsp)) {
1101                                 /*
1102                                  * Connect failed -- the DCS may not
1103                                  * be up yet, so we'll try again later
1104                                  */
1105                                 HARP_TIMER(&dcsp->sd_open_t,
1106                                                 SCSP_Open_Interval,
1107                                                 scsp_open_timeout);
1108                         }
1109                 }
1110                 ssp->ss_state = SCSP_SS_ACTIVE;
1111                 break;
1112         case SCSP_SOLICIT_RSP:
1113                 /*
1114                  * The server has answered our request for a particular
1115                  * entry from its cache
1116                  */
1117                 dcsp = (Scsp_dcs *)msg->si_tok;
1118                 rc = scsp_cfsm(dcsp, SCSP_CIFSM_SOL_RSP, (Scsp_msg *)0,
1119                                 msg);
1120                 break;
1121         case SCSP_UPDATE_REQ:
1122                 /*
1123                  * Pass the update request to the FSMs for all
1124                  * DCSs associated with the server
1125                  */
1126                 if (ssp->ss_state == SCSP_SS_ACTIVE) {
1127                         for (dcsp = ssp->ss_dcs; dcsp;
1128                                         dcsp = dcsp->sd_next) {
1129                                 rc = scsp_cfsm(dcsp, SCSP_CIFSM_UPD_REQ,
1130                                                 (Scsp_msg *)0, msg);
1131                         }
1132                 }
1133                 break;
1134         case SCSP_UPDATE_RSP:
1135                 /*
1136                  * Pass the update response to the FSM for the
1137                  * DCS associated with the request
1138                  */
1139                 dcsp = (Scsp_dcs *)msg->si_tok;
1140                 rc = scsp_cfsm(dcsp, SCSP_CIFSM_UPD_RSP,
1141                                 (Scsp_msg *)0, msg);
1142                 break;
1143         default:
1144                 scsp_log(LOG_ERR, "invalid message type %d from server",
1145                                 msg->si_type);
1146                 return(EINVAL);
1147         }
1148
1149         UM_FREE(msg);
1150         return(0);
1151 }
1152
1153
1154 /*
1155  * Send a Cache Indication to a server
1156  *
1157  * Arguments:
1158  *      ssp     pointer to server block block
1159  *
1160  * Returns:
1161  *      0       success
1162  *      else    errno indicating reason for failure
1163  *
1164  */
1165 int
1166 scsp_send_cache_ind(Scsp_server *ssp)
1167 {
1168         int             rc;
1169         Scsp_if_msg     *msg;
1170
1171         /*
1172          * Get storage for a server interface message
1173          */
1174         msg = (Scsp_if_msg *)UM_ALLOC(sizeof(Scsp_if_msg));
1175         if (!msg) {
1176                 scsp_mem_err("scsp_send_cache_ind: sizeof(Scsp_if_msg)");
1177         }
1178         UM_ZERO(msg, sizeof(Scsp_if_msg));
1179
1180         /*
1181          * Fill out the message
1182          */
1183         msg->si_type = SCSP_CACHE_IND;
1184         msg->si_rc = 0;
1185         msg->si_proto = ssp->ss_pid;
1186         msg->si_len = sizeof(Scsp_if_msg_hdr);
1187         msg->si_tok = (u_long)ssp;
1188
1189         /*
1190          * Send the message
1191          */
1192         rc = scsp_if_sock_write(ssp->ss_sock, msg);
1193         UM_FREE(msg);
1194         return(rc);
1195 }
1196
1197
1198 /*
1199  * Read data from a pending server connection
1200  *
1201  * Arguments:
1202  *      psp     pointer to pending block that has data
1203  *
1204  * Returns:
1205  *      0       success
1206  *      else    errno indicating reason for failure
1207  *
1208  */
1209 int
1210 scsp_pending_read(Scsp_pending *psp)
1211 {
1212         int             rc;
1213         Scsp_server     *ssp;
1214         Scsp_if_msg     *msg;
1215
1216         /*
1217          * Read the message from the pending socket
1218          */
1219         msg = scsp_if_sock_read(psp->sp_sock);
1220         if (!msg) {
1221                 rc = errno;
1222                 goto pending_read_fail;
1223         }
1224
1225         /*
1226          * Make sure this is configuration data
1227          */
1228         if (msg->si_type != SCSP_CFG_REQ) {
1229                 scsp_log(LOG_ERR, "invalid message type %d from pending server",
1230                                 msg->si_type);
1231                 rc = EINVAL;
1232                 goto pending_read_fail;
1233         }
1234
1235         /*
1236          * Find the server this message is for
1237          */
1238         for (ssp = scsp_server_head; ssp; ssp = ssp->ss_next) {
1239                 if (strcmp(ssp->ss_intf, msg->si_cfg.atmarp_netif) == 0)
1240                         break;
1241         }
1242         if (!ssp) {
1243                 scsp_log(LOG_ERR, "refused connection from server for %s",
1244                                 msg->si_cfg.atmarp_netif);
1245                 rc = EINVAL;
1246                 goto config_reject;
1247         }
1248
1249         /*
1250          * Make sure the server is ready to go
1251          */
1252         rc = scsp_get_server_info(ssp);
1253         if (rc) {
1254                 goto config_reject;
1255         }
1256
1257         /*
1258          * Save the socket
1259          */
1260         ssp->ss_sock = psp->sp_sock;
1261         ssp->ss_state = SCSP_SS_CFG;
1262         UNLINK(psp, Scsp_pending, scsp_pending_head, sp_next);
1263         UM_FREE(psp);
1264
1265         /*
1266          * Listen for connections from the server's DCSs
1267          */
1268         rc = scsp_dcs_listen(ssp);
1269         if (rc < 0) {
1270                 rc = errno;
1271                 goto config_reject;
1272         }
1273
1274         /*
1275          * Respond to the configuration message
1276          */
1277         msg->si_type = SCSP_CFG_RSP;
1278         msg->si_rc = SCSP_RSP_OK;
1279         msg->si_len = sizeof(Scsp_if_msg_hdr);
1280         rc = scsp_if_sock_write(ssp->ss_sock, msg);
1281         if (rc) {
1282                 goto config_error;;
1283         }
1284
1285         /*
1286          * Ask the server to send us its cache
1287          */
1288         rc = scsp_send_cache_ind(ssp);
1289         if (rc) {
1290                 goto config_error;
1291         }
1292
1293         UM_FREE(msg);
1294         return(0);
1295
1296 config_reject:
1297         /*
1298          * Respond to the configuration message
1299          */
1300         msg->si_type = SCSP_CFG_RSP;
1301         msg->si_rc = SCSP_RSP_REJ;
1302         msg->si_len = sizeof(Scsp_if_msg_hdr);
1303         scsp_if_sock_write(ssp->ss_sock, msg);
1304
1305 config_error:
1306         if (ssp->ss_sock != -1) {
1307                 close(ssp->ss_sock);
1308                 ssp->ss_sock = -1;
1309         }
1310         if (ssp->ss_dcs_lsock != -1) {
1311                 close(ssp->ss_dcs_lsock);
1312                 ssp->ss_sock = -1;
1313         }
1314         ssp->ss_state = SCSP_SS_NULL;
1315         UM_FREE(msg);
1316
1317         return(rc);
1318
1319 pending_read_fail:
1320         /*
1321          * Close the socket and free the pending read block
1322          */
1323         close(psp->sp_sock);
1324         UNLINK(psp, Scsp_pending, scsp_pending_head, sp_next);
1325         UM_FREE(psp);
1326         if (msg)
1327                 UM_FREE(msg);
1328         return(rc);
1329 }