kernel: Sync ACPICA with Intel's version 20140424.
[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.5 2006/08/03 16:40:48 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(NULL);
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(NULL);
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 = NULL;
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, NULL);
781         }
782         if (errno == ECONNREFUSED) {
783                 /*
784                  * VCC open failed--set a timer and try
785                  * again when it fires
786                  */
787                 HARP_TIMER(&dcsp->sd_open_t,
788                                 SCSP_Open_Interval,
789                                 scsp_open_timeout);
790                 rc = 0;
791         }
792
793         if (buff)
794                 UM_FREE(buff);
795         return(rc);
796 }
797
798
799 /*
800  * Listen for Unix connections from SCSP client servers
801  *
802  * Arguments:
803  *      None
804  *
805  * Returns:
806  *      sock    socket which is listening
807  *      -1      error (reason in errno)
808  *
809  */
810 int
811 scsp_server_listen(void)
812 {
813         int     rc, sd;
814
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 */
821         };
822
823         /*
824          * Unlink any old socket
825          */
826         rc = unlink(SCSPD_SOCK_NAME);
827         if (rc < 0 && errno != ENOENT)
828                 return(-1);
829
830         /*
831          * Open a socket
832          */
833         sd = socket(PF_UNIX, SOCK_STREAM, 0);
834         if (sd == -1) {
835                 return(-1);
836         }
837         if (sd > scsp_max_socket) {
838                 scsp_max_socket = sd;
839         }
840
841         /*
842          * Bind the socket's address
843          */
844         rc = bind(sd, &scsp_addr, sizeof(scsp_addr));
845         if (rc == -1) {
846                 close(sd);
847                 return(-1);
848         }
849
850         /*
851          * Set non-blocking I/O
852          */
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);
861         }
862
863         /*
864          * Listen for new connections
865          */
866         if (listen(sd, 5) < 0) {
867                 close(sd);
868                 return(-1);
869         }
870
871         return(sd);
872 }
873
874
875 /*
876  * Accept a connection from a server
877  *
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.
882  *
883  * Arguments:
884  *      ls      listening socket to accept from
885  *
886  * Returns:
887  *      0       success
888  *      errno   reason for failure
889  *
890  */
891 int
892 scsp_server_accept(int ls)
893 {
894         int             len, rc, sd;
895         struct sockaddr server_addr;
896         Scsp_pending    *psp;
897
898         /*
899          * Accept the new connection
900          */
901         len = sizeof(server_addr);
902         sd = accept(ls, (struct sockaddr *)&server_addr, &len);
903         if (sd < 0) {
904                 return(errno);
905         }
906         if (sd > scsp_max_socket) {
907                 scsp_max_socket = sd;
908         }
909
910         /*
911          * Set non-blocking operation
912          */
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;
921         }
922
923         /*
924          * Put the new socket on the 'pending' queue
925          */
926         psp = (Scsp_pending *) UM_ALLOC(sizeof(Scsp_pending));
927         if (!psp) {
928                 scsp_mem_err("scsp_server_accept: sizeof(Scsp_pending)");
929         }
930         psp->sp_sock = sd;
931         LINK2TAIL(psp, Scsp_pending, scsp_pending_head, sp_next);
932
933         return(0);
934 }
935
936
937 /*
938  * Read a server interface message from a socket
939  *
940  * Arguments:
941  *      sd      socket to read from
942  *
943  * Returns:
944  *      msg     pointer to message read
945  *      0       failure (errno has reason)
946  *
947  */
948 Scsp_if_msg *
949 scsp_if_sock_read(int sd)
950 {
951         int             len;
952         char            *buff = NULL;
953         Scsp_if_msg     *msg;
954         Scsp_if_msg_hdr msg_hdr;
955
956         /*
957          * Read the message header from the socket
958          */
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;
964         }
965
966         /*
967          * Get a buffer and read the rest of the message into it
968          */
969         buff = (char *)UM_ALLOC(msg_hdr.sh_len);
970         if (!buff) {
971                 scsp_mem_err("scsp_if_sock_read: msg_hdr.sh_len");
972         }
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;
980                 }
981                 goto socket_read_fail;
982         }
983
984         /*
985          * Trace the message
986          */
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");
991         }
992
993         return(msg);
994
995 socket_read_fail:
996         if (buff)
997                 UM_FREE(buff);
998         return(NULL);
999 }
1000
1001
1002 /*
1003  * Write a server interface message to a socket
1004  *
1005  * Arguments:
1006  *      sd      socket to write to
1007  *      msg     pointer to message to write
1008  *
1009  * Returns:
1010  *      0       success
1011  *      errno   reason for failure
1012  *
1013  */
1014 int
1015 scsp_if_sock_write(int sd, Scsp_if_msg *msg)
1016 {
1017         int     len, rc;
1018
1019         /*
1020          * Trace the message
1021          */
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");
1026         }
1027
1028         /*
1029          * Write the message to the indicated socket
1030          */
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;
1039         }
1040
1041         return(rc);
1042 }
1043
1044
1045 /*
1046  * Read data from a local server
1047  *
1048  * Arguments:
1049  *      ssp     pointer to server block that has data
1050  *
1051  * Returns:
1052  *      0       success
1053  *      else    errno indicating reason for failure
1054  *
1055  */
1056 int
1057 scsp_server_read(Scsp_server *ssp)
1058 {
1059         int             rc;
1060         Scsp_dcs        *dcsp;
1061         Scsp_if_msg     *msg;
1062
1063         /*
1064          * Read the message
1065          */
1066         msg = scsp_if_sock_read(ssp->ss_sock);
1067         if (!msg) {
1068                 if (errno == EWOULDBLOCK) {
1069                         /*
1070                          * Nothing to read--just return
1071                          */
1072                         return(0);
1073                 } else {
1074                         /*
1075                          * Error--shut down the server entry
1076                          */
1077                         scsp_server_shutdown(ssp);
1078                 }
1079                 return(errno);
1080         }
1081
1082         /*
1083          * Process the received message
1084          */
1085         switch(msg->si_type) {
1086         case SCSP_NOP_REQ:
1087                 /*
1088                  * Ignore a NOP
1089                  */
1090                 break;
1091         case SCSP_CACHE_RSP:
1092                 /*
1093                  * Summarize the server's cache and try to open
1094                  * connections to all of its DCSs
1095                  */
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)) {
1100                                 /*
1101                                  * Connect failed -- the DCS may not
1102                                  * be up yet, so we'll try again later
1103                                  */
1104                                 HARP_TIMER(&dcsp->sd_open_t,
1105                                                 SCSP_Open_Interval,
1106                                                 scsp_open_timeout);
1107                         }
1108                 }
1109                 ssp->ss_state = SCSP_SS_ACTIVE;
1110                 break;
1111         case SCSP_SOLICIT_RSP:
1112                 /*
1113                  * The server has answered our request for a particular
1114                  * entry from its cache
1115                  */
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:
1120                 /*
1121                  * Pass the update request to the FSMs for all
1122                  * DCSs associated with the server
1123                  */
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);
1129                         }
1130                 }
1131                 break;
1132         case SCSP_UPDATE_RSP:
1133                 /*
1134                  * Pass the update response to the FSM for the
1135                  * DCS associated with the request
1136                  */
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);
1144         }
1145
1146         UM_FREE(msg);
1147         return(0);
1148 }
1149
1150
1151 /*
1152  * Send a Cache Indication to a server
1153  *
1154  * Arguments:
1155  *      ssp     pointer to server block block
1156  *
1157  * Returns:
1158  *      0       success
1159  *      else    errno indicating reason for failure
1160  *
1161  */
1162 int
1163 scsp_send_cache_ind(Scsp_server *ssp)
1164 {
1165         int             rc;
1166         Scsp_if_msg     *msg;
1167
1168         /*
1169          * Get storage for a server interface message
1170          */
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)");
1174         }
1175         UM_ZERO(msg, sizeof(Scsp_if_msg));
1176
1177         /*
1178          * Fill out the message
1179          */
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;
1185
1186         /*
1187          * Send the message
1188          */
1189         rc = scsp_if_sock_write(ssp->ss_sock, msg);
1190         UM_FREE(msg);
1191         return(rc);
1192 }
1193
1194
1195 /*
1196  * Read data from a pending server connection
1197  *
1198  * Arguments:
1199  *      psp     pointer to pending block that has data
1200  *
1201  * Returns:
1202  *      0       success
1203  *      else    errno indicating reason for failure
1204  *
1205  */
1206 int
1207 scsp_pending_read(Scsp_pending *psp)
1208 {
1209         int             rc;
1210         Scsp_server     *ssp;
1211         Scsp_if_msg     *msg;
1212
1213         /*
1214          * Read the message from the pending socket
1215          */
1216         msg = scsp_if_sock_read(psp->sp_sock);
1217         if (!msg) {
1218                 rc = errno;
1219                 goto pending_read_fail;
1220         }
1221
1222         /*
1223          * Make sure this is configuration data
1224          */
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;
1230         }
1231
1232         /*
1233          * Find the server this message is for
1234          */
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;
1238         }
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;
1244         }
1245
1246         /*
1247          * Make sure the server is ready to go
1248          */
1249         rc = scsp_get_server_info(ssp);
1250         if (rc) {
1251                 goto config_reject;
1252         }
1253
1254         /*
1255          * Save the socket
1256          */
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);
1261
1262         /*
1263          * Listen for connections from the server's DCSs
1264          */
1265         rc = scsp_dcs_listen(ssp);
1266         if (rc < 0) {
1267                 rc = errno;
1268                 goto config_reject;
1269         }
1270
1271         /*
1272          * Respond to the configuration message
1273          */
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;
1280         }
1281
1282         /*
1283          * Ask the server to send us its cache
1284          */
1285         rc = scsp_send_cache_ind(ssp);
1286         if (rc) {
1287                 goto config_error;
1288         }
1289
1290         UM_FREE(msg);
1291         return(0);
1292
1293 config_reject:
1294         /*
1295          * Respond to the configuration message
1296          */
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);
1301
1302 config_error:
1303         if (ssp->ss_sock != -1) {
1304                 close(ssp->ss_sock);
1305                 ssp->ss_sock = -1;
1306         }
1307         if (ssp->ss_dcs_lsock != -1) {
1308                 close(ssp->ss_dcs_lsock);
1309                 ssp->ss_sock = -1;
1310         }
1311         ssp->ss_state = SCSP_SS_NULL;
1312         UM_FREE(msg);
1313
1314         return(rc);
1315
1316 pending_read_fail:
1317         /*
1318          * Close the socket and free the pending read block
1319          */
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);
1326 }