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