]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/atm/scspd/scsp_config.c
merge fix for boot-time hang on centos' xen
[FreeBSD/FreeBSD.git] / usr.sbin / atm / scspd / scsp_config.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$
27  *
28  */
29
30 /*
31  * Server Cache Synchronization Protocol (SCSP) Support
32  * ----------------------------------------------------
33  *
34  * Configuration file processing
35  *
36  */
37
38 #include <sys/types.h>
39 #include <sys/param.h>
40 #include <sys/socket.h>
41 #include <net/if.h>
42 #include <netinet/in.h>
43 #include <netatm/port.h> 
44 #include <netatm/queue.h> 
45 #include <netatm/atm.h>
46 #include <netatm/atm_if.h>
47 #include <netatm/atm_sap.h>
48 #include <netatm/atm_sys.h>
49 #include <netatm/atm_ioctl.h>
50   
51 #include <errno.h>
52 #include <libatm.h>
53 #include <stdio.h>
54 #include <stdlib.h>
55 #include <string.h>
56 #include <syslog.h>
57
58 #include "scsp_msg.h"
59 #include "scsp_if.h"
60 #include "scsp_var.h"
61
62 #ifndef lint
63 __RCSID("@(#) $FreeBSD$");
64 #endif
65
66
67 extern int      yyparse(void);
68
69 /*
70  * Global variables
71  */
72 FILE            *cfg_file;
73 Scsp_server     *current_server;
74 Scsp_dcs        *current_dcs;
75
76
77 /*
78  * Process the configuration file
79  *
80  * This routine is called when the daemon starts, and it can also be
81  * called while it is running, as the result of a SIGHUP signal.  It
82  * therefore has to be capable of both configuring the daemon from
83  * scratch and modifying the configuration of a running daemon.
84  *
85  * Arguments:
86  *      cfn     configuration file name
87  *
88  * Returns:
89  *      0       configuration read with no errors
90  *      else    error found in configuration file
91  *
92  */
93 int
94 scsp_config(cfn)
95         char    *cfn;
96 {
97         int             rc;
98         Scsp_server     *ssp, *snext;
99
100         /*
101          * Open the configuration file
102          */
103         cfg_file = fopen(cfn, "r");
104         if (!cfg_file) {
105                 scsp_log(LOG_ERR, "can't open config file %s",
106                                 (void *)cfn);
107                 exit(1);
108         }
109
110         /*
111          * Initialize current interface pointer
112          */
113         current_server = (Scsp_server *)0;
114
115         /*
116          * Clear marks on any existing servers
117          */
118         for (ssp = scsp_server_head; ssp; ssp = ssp->ss_next) {
119                 ssp->ss_mark = 0;
120         }
121
122         /*
123          * Scan the configuration file, processing each line as
124          * it is read
125          */
126         rc = yyparse();
127
128         /*
129          * Close the configuration file
130          */
131         fclose(cfg_file);
132
133         /*
134          * Delete any server entries that weren't updated
135          */
136         for (ssp = scsp_server_head; ssp; ssp = snext) {
137                 snext = ssp->ss_next;
138                 if (!ssp->ss_mark)
139                         scsp_server_delete(ssp);
140         }
141
142         return(rc);
143 }
144
145
146 /*
147  * Prepare for SCSP DCS setup
148  *
149  * This routine is called from yyparse() when a DCS command is found.
150  *
151  * Arguments:
152  *      none
153  *
154  * Returns:
155  *      0       success
156  *      1       error encountered
157  *
158  */
159 int
160 start_dcs()
161 {
162         Scsp_dcs                *dcsp;
163
164         /*
165          * Make sure we have a current server block
166          */
167         if (!current_server) {
168                 parse_error("server not found");
169                 return(1);
170         }
171
172         /*
173          * Allocate a DCS block
174          */
175         dcsp = calloc(1, sizeof(Scsp_dcs));
176         if (dcsp == NULL)
177                 scsp_mem_err("start_dcs: sizeof(Scsp_dcs)");
178
179         /*
180          * Fill out DCS links and default values
181          */
182         dcsp->sd_server = current_server;
183         dcsp->sd_addr.address_format = T_ATM_ABSENT;
184         dcsp->sd_subaddr.address_format = T_ATM_ABSENT;
185         dcsp->sd_sock = -1;
186         dcsp->sd_ca_rexmt_int = SCSP_CAReXmitInterval;
187         dcsp->sd_csus_rexmt_int = SCSP_CSUSReXmitInterval;
188         dcsp->sd_hops = SCSP_CSA_HOP_CNT;
189         dcsp->sd_csu_rexmt_int = SCSP_CSUReXmitInterval;
190         dcsp->sd_csu_rexmt_max = SCSP_CSUReXmitMax;
191         LINK2TAIL(dcsp, Scsp_dcs, current_server->ss_dcs, sd_next);
192
193         current_dcs = dcsp;
194         return(0);
195 }
196
197
198 /*
199  * Finish up server configuration
200  *
201  * This routine is called from yyparse() to at the end of a DCS
202  * command.  It checks that required fields are set and finishes
203  * up the DCS block.
204  *
205  * Arguments:
206  *      none
207  *
208  * Returns:
209  *      0       success
210  *      1       error encountered
211  *
212  */
213 int
214 finish_dcs()
215 {
216         int             rc = 0;
217         Scsp_dcs        *dcsp;
218         Scsp_server     *ssp;
219
220         /*
221          * Make sure we have a current server block and DCS block
222          */
223         if (!current_server) {
224                 parse_error("server not found");
225                 return(1);
226         }
227
228         if (!current_dcs) {
229                 parse_error("server not found");
230                 return(1);
231         }
232         ssp = current_server;
233         dcsp = current_dcs;
234
235         /*
236          * Make sure the DCS ID is set
237          */
238         if (dcsp->sd_dcsid.id_len == 0) {
239                 parse_error("DCS ID not set");
240                 rc++;
241         }
242
243         /*
244          * Make sure the ATM address is set
245          */
246         if (dcsp->sd_addr.address_format == T_ATM_ABSENT) {
247                 parse_error("DCS ATM address not set");
248                 rc++;
249         }
250
251         current_dcs = (Scsp_dcs *)0;
252         return(rc);
253 }
254
255
256 /*
257  * Configure DCS ATM address
258  *
259  * This routine is called from yyparse() to process an ATMaddr command.
260  *
261  * Arguments:
262  *      ap      pointer to DCS's ATM address (in ASCII)
263  *      sap     pointer to DCS's ATM subaddress (in ASCII)
264  *
265  * Returns:
266  *      0       success
267  *      1       error encountered
268  *
269  */
270 int
271 set_dcs_addr(ap, sap)
272         char    *ap, *sap;
273 {
274         Scsp_dcs                *dcsp;
275         Atm_addr                addr, subaddr;
276
277         /*
278          * Make sure we have a current server block and DCS block
279          */
280         if (!current_server) {
281                 parse_error("server not found");
282                 return(1);
283         }
284
285         if (!current_dcs) {
286                 parse_error("server not found");
287                 return(1);
288         }
289         dcsp = current_dcs;
290
291         /*
292          * Initialize
293          */
294         bzero(&addr, sizeof(addr));
295         addr.address_format = T_ATM_ABSENT;
296         bzero(&subaddr, sizeof(subaddr));
297         subaddr.address_format = T_ATM_ABSENT;
298
299         /*
300          * Convert the ATM address from character to internal format
301          */
302         if (ap) {
303                 addr.address_length = get_hex_atm_addr(ap,
304                                 (u_char *)addr.address, strlen(ap));
305                 if (addr.address_length == 0) {
306                         parse_error("invalid ATM address");
307                         return(1);
308                 }
309                 if (addr.address_length == sizeof(Atm_addr_nsap)) {
310                         addr.address_format = T_ATM_ENDSYS_ADDR;
311                 } else if (addr.address_length <=
312                                 sizeof(Atm_addr_e164)) {
313                         addr.address_format = T_ATM_E164_ADDR;
314                 } else {
315                         parse_error("invalid ATM address");
316                         return(1);
317                 }
318         }
319
320         /*
321          * Convert the ATM subaddress from character to internal format
322          */
323         if (sap) {
324                 subaddr.address_length = get_hex_atm_addr(sap,
325                                 (u_char *)subaddr.address, strlen(sap));
326                 if (subaddr.address_length == 0) {
327                         parse_error("invalid ATM address");
328                         return(1);
329                 }
330                 if (subaddr.address_length == sizeof(Atm_addr_nsap)) {
331                         subaddr.address_format = T_ATM_ENDSYS_ADDR;
332                 } else if (subaddr.address_length <=
333                                 sizeof(Atm_addr_e164)) {
334                         subaddr.address_format = T_ATM_E164_ADDR;
335                 } else {
336                         parse_error("invalid ATM subaddress");
337                         return(1);
338                 }
339         }
340
341         /*
342          * Make sure we have a legal ATM address type combination
343          */
344         if (((addr.address_format != T_ATM_ENDSYS_ADDR) ||
345                         (subaddr.address_format != T_ATM_ABSENT)) &&
346                         ((addr.address_format != T_ATM_E164_ADDR) ||
347                         (subaddr.address_format != T_ATM_ENDSYS_ADDR))) {
348                 parse_error("invalid address/subaddress combination");
349                 return(1);
350         }
351
352         /*
353          * Save the address and subaddress
354          */
355         ATM_ADDR_COPY(&addr, &dcsp->sd_addr);
356         ATM_ADDR_COPY(&subaddr, &dcsp->sd_subaddr);
357
358         return(0);
359 }
360
361
362 /*
363  * Configure CA retransmit interval for DCS
364  *
365  * This routine is called from yyparse() to process a CAReXmitInt
366  * command.
367  *
368  * Arguments:
369  *      val     time interval
370  *
371  * Returns:
372  *      0       success
373  *      1       error encountered
374  *
375  */
376 int
377 set_dcs_ca_rexmit(val)
378         int     val;
379 {
380         Scsp_dcs        *dcsp;
381
382         /*
383          * Make sure we have a current server block and DCS block
384          */
385         if (!current_server) {
386                 parse_error("server not found");
387                 return(1);
388         }
389
390         if (!current_dcs) {
391                 parse_error("server not found");
392                 return(1);
393         }
394         dcsp = current_dcs;
395
396
397         /*
398          * Validate the interval
399          */
400         if (val <= 0 || val > 1024) {
401                 parse_error("invalid CA retransmit interval");
402                 return(1);
403         }
404
405         /*
406          * Set CA retransmit interval
407          */
408         dcsp->sd_ca_rexmt_int = val;
409
410         return(0);
411 }
412
413
414 /*
415  * Configure CSUS retransmit interval for DCS
416  *
417  * This routine is called from yyparse() to process a CSUSReXmitInt
418  * command.
419  *
420  * Arguments:
421  *      val     time interval
422  *
423  * Returns:
424  *      0       success
425  *      1       error encountered
426  *
427  */
428 int
429 set_dcs_csus_rexmit(val)
430         int     val;
431 {
432         Scsp_dcs        *dcsp;
433
434         /*
435          * Make sure we have a current server block and DCS block
436          */
437         if (!current_server) {
438                 parse_error("server not found");
439                 return(1);
440         }
441
442         if (!current_dcs) {
443                 parse_error("server not found");
444                 return(1);
445         }
446         dcsp = current_dcs;
447
448
449         /*
450          * Validate the interval
451          */
452         if (val <= 0 || val > 1024) {
453                 parse_error("invalid CSUS retransmit interval");
454                 return(1);
455         }
456
457         /*
458          * Set CSUS retransmit interval
459          */
460         dcsp->sd_csus_rexmt_int = val;
461
462         return(0);
463 }
464
465
466 /*
467  * Configure CSU retransmit interval for DCS
468  *
469  * This routine is called from yyparse() to process a CSUReXmitInt
470  * command.
471  *
472  * Arguments:
473  *      val     time interval
474  *
475  * Returns:
476  *      0       success
477  *      1       error encountered
478  *
479  */
480 int
481 set_dcs_csu_rexmit(val)
482         int     val;
483 {
484         Scsp_dcs        *dcsp;
485
486         /*
487          * Make sure we have a current server block and DCS block
488          */
489         if (!current_server) {
490                 parse_error("server not found");
491                 return(1);
492         }
493
494         if (!current_dcs) {
495                 parse_error("server not found");
496                 return(1);
497         }
498         dcsp = current_dcs;
499
500
501         /*
502          * Validate the interval
503          */
504         if (val <= 0 || val > 1024) {
505                 parse_error("invalid CSU retransmit interval");
506                 return(1);
507         }
508
509         /*
510          * Set CSU retransmit interval
511          */
512         dcsp->sd_csu_rexmt_int = val;
513
514         return(0);
515 }
516
517
518 /*
519  * Configure CSU retransmit limit for DCS
520  *
521  * This routine is called from yyparse() to process a CSUReXmitMax
522  * command.
523  *
524  * Arguments:
525  *      val     time interval
526  *
527  * Returns:
528  *      0       success
529  *      1       error encountered
530  *
531  */
532 int
533 set_dcs_csu_rexmit_max(val)
534         int     val;
535 {
536         Scsp_dcs        *dcsp;
537
538         /*
539          * Make sure we have a current server block and DCS block
540          */
541         if (!current_server) {
542                 parse_error("server not found");
543                 return(1);
544         }
545
546         if (!current_dcs) {
547                 parse_error("server not found");
548                 return(1);
549         }
550         dcsp = current_dcs;
551
552
553         /*
554          * Validate the interval
555          */
556         if (val <= 0 || val > 1024) {
557                 parse_error("invalid CSU retransmit maximum");
558                 return(1);
559         }
560
561         /*
562          * Set CSU retransmit limit
563          */
564         dcsp->sd_csu_rexmt_max = val;
565
566         return(0);
567 }
568
569
570 /*
571  * Configure Hello dead factor for DCS
572  *
573  * This routine is called from yyparse() to process a HelloDead
574  * command.
575  *
576  * Arguments:
577  *      val     number of times Hello interval has to expire before
578  *              a DCS is considered dead
579  *
580  * Returns:
581  *      0       success
582  *      1       error encountered
583  *
584  */
585 int
586 set_dcs_hello_df(val)
587         int     val;
588 {
589         Scsp_dcs        *dcsp;
590
591         /*
592          * Make sure we have a current server block and DCS block
593          */
594         if (!current_server) {
595                 parse_error("server not found");
596                 return(1);
597         }
598
599         if (!current_dcs) {
600                 parse_error("server not found");
601                 return(1);
602         }
603         dcsp = current_dcs;
604
605
606         /*
607          * Validate the limit
608          */
609         if (val <= 0 || val > 1024) {
610                 parse_error("invalid Hello dead factor");
611                 return(1);
612         }
613
614         /*
615          * Set Hello dead factor
616          */
617         dcsp->sd_hello_df = val;
618
619         return(0);
620 }
621
622
623 /*
624  * Configure Hello interval for DCS
625  *
626  * This routine is called from yyparse() to process a HelloInt
627  * command.
628  *
629  * Arguments:
630  *      val     time interval
631  *
632  * Returns:
633  *      0       success
634  *      1       error encountered
635  *
636  */
637 int
638 set_dcs_hello_int(val)
639         int     val;
640 {
641         Scsp_dcs        *dcsp;
642
643         /*
644          * Make sure we have a current server block and DCS block
645          */
646         if (!current_server) {
647                 parse_error("server not found");
648                 return(1);
649         }
650
651         if (!current_dcs) {
652                 parse_error("server not found");
653                 return(1);
654         }
655         dcsp = current_dcs;
656
657
658         /*
659          * Validate the interval
660          */
661         if (val <= 0 || val > 1024) {
662                 parse_error("invalid Hello interval");
663                 return(1);
664         }
665
666         /*
667          * Set Hello interval
668          */
669         dcsp->sd_hello_int = val;
670
671         return(0);
672 }
673
674
675 /*
676  * Configure hop count for SCSP server
677  *
678  * This routine is called from yyparse() to process a Hops command.
679  *
680  * Arguments:
681  *      hops    number of hops
682  *
683  * Returns:
684  *      0       success
685  *      1       error encountered
686  *
687  */
688 int
689 set_dcs_hops(hops)
690         int     hops;
691 {
692         Scsp_dcs        *dcsp;
693
694         /*
695          * Make sure we have a current server block and DCS block
696          */
697         if (!current_server) {
698                 parse_error("server not found");
699                 return(1);
700         }
701
702         if (!current_dcs) {
703                 parse_error("server not found");
704                 return(1);
705         }
706         dcsp = current_dcs;
707
708
709         /*
710          * Validate the count
711          */
712         if (hops <= 0 || hops > 1024) {
713                 parse_error("invalid hop count");
714                 return(1);
715         }
716
717         /*
718          * Set hop count
719          */
720         dcsp->sd_hops = hops;
721
722         return(0);
723 }
724
725
726 /*
727  * Configure DCS ID
728  *
729  * This routine is called from yyparse() to process an ID command.
730  *
731  * Arguments:
732  *      name    pointer to DCS's DNS name or IP address (in ASCII)
733  *
734  * Returns:
735  *      0       success
736  *      1       error encountered
737  *
738  */
739 int
740 set_dcs_id(name)
741         char    *name;
742 {
743         Scsp_dcs                *dcsp;
744         Scsp_server             *ssp;
745         struct sockaddr_in      *ip_addr;
746
747         /*
748          * Make sure we have a current server block and DCS block
749          */
750         if (!current_server) {
751                 parse_error("server not found");
752                 return(1);
753         }
754
755         if (!current_dcs) {
756                 parse_error("server not found");
757                 return(1);
758         }
759         ssp = current_server;
760         dcsp = current_dcs;
761
762         /*
763          * Convert the DNS name or IP address
764          */
765         ip_addr = get_ip_addr(name);
766         if (!ip_addr) {
767                 parse_error("invalid DCS IP address");
768                 return(1);
769         }
770
771         /*
772          * Verify the address length
773          */
774         if (ssp->ss_id_len != sizeof(ip_addr->sin_addr)) {
775                 parse_error("invalid DCS ID length");
776                 return(1);
777         }
778
779         /*
780          * Set the ID in the DCS block
781          */
782         dcsp->sd_dcsid.id_len = ssp->ss_id_len;
783         bcopy(&ip_addr->sin_addr, dcsp->sd_dcsid.id, ssp->ss_id_len);
784
785         return(0);
786 }
787
788
789 /*
790  * Configure network interface for SCSP server
791  *
792  * This routine is called from yyparse() to process a Netif command.
793  * It verifies the network interface name, gets interface information
794  * from the kernel, and sets the appropriate fields in the server
795  * control block.
796  *
797  * Arguments:
798  *      netif   pointer to network interface name
799  *
800  * Returns:
801  *      0       success
802  *      1       error encountered
803  *
804  */
805 int
806 set_intf(netif)
807         char    *netif;
808 {
809         int                     rc;
810         Scsp_server             *ssp;
811
812         /*
813          * Get the current network interface address
814          */
815         ssp = current_server;
816         if (!ssp) {
817                 parse_error("Server not found");
818                 rc = 1;
819                 goto set_intf_done;
820         }
821
822         /*
823          * Make sure we're configuring a valid
824          * network interface
825          */
826         rc = verify_nif_name(netif);
827         if (rc == 0) {
828                 parse_error("%s is not a valid network interface",
829                                 (void *)netif);
830                 rc = 1;
831                 goto set_intf_done;
832         } else if (rc < 0) {
833                 scsp_log(LOG_ERR, "Netif name verify error");
834                 exit(1);
835         }
836
837         /*
838          * Save the server's network interface name
839          */
840         strcpy(ssp->ss_intf, netif);
841         rc = 0;
842
843 set_intf_done:
844         return(rc);
845 }
846
847
848 /*
849  * Configure protocol for SCSP server
850  *
851  * This routine is called from yyparse() to process a Protocol command.
852  *
853  * Arguments:
854  *      proto   SCSP protocol being configured
855  *
856  * Returns:
857  *      0       success
858  *      1       error encountered
859  *
860  */
861 int
862 set_protocol(proto)
863         int     proto;
864 {
865         Scsp_server     *ssp;
866
867         /*
868          * Get address of current server block
869          */
870         ssp = current_server;
871         if (!ssp) {
872                 parse_error("server not found");
873                 return(1);
874         }
875
876         /*
877          * Process based on protocol ID
878          */
879         switch(proto) {
880         case SCSP_PROTO_ATMARP:
881                 ssp->ss_pid = proto;
882                 ssp->ss_id_len = SCSP_ATMARP_ID_LEN;
883                 ssp->ss_ckey_len = SCSP_ATMARP_KEY_LEN;
884                 break;
885         case SCSP_PROTO_NHRP:
886                 ssp->ss_pid = proto;
887                 ssp->ss_id_len = SCSP_NHRP_ID_LEN;
888                 ssp->ss_ckey_len = SCSP_NHRP_KEY_LEN;
889                 break;
890         case SCSP_PROTO_MARS:
891         case SCSP_PROTO_DHCP:
892         case SCSP_PROTO_LNNI:
893         default:
894                 parse_error("invalid protocol");
895                 return(1);
896         }
897
898         return(0);
899 }
900
901
902 /*
903  * Configure server group for SCSP server
904  *
905  * This routine is called from yyparse() to process a ServerGroupID
906  * command.
907  *
908  * Arguments:
909  *      sgid    server group id
910  *
911  * Returns:
912  *      0       success
913  *      1       error encountered
914  *
915  */
916 int
917 set_server_group(sgid)
918         int     sgid;
919 {
920         Scsp_server     *ssp;
921
922         /*
923          * Get address of current server block
924          */
925         ssp = current_server;
926         if (!ssp) {
927                 parse_error("server not found");
928                 return(1);
929         }
930
931         /*
932          * Validate server group ID
933          */
934         if (sgid <= 0) {
935                 parse_error("invalid server group ID");
936                 return(1);
937         }
938
939         /*
940          * Save the ID
941          */
942         ssp->ss_sgid = sgid;
943
944         return(0);
945 }
946
947
948 /*
949  * Prepare for SCSP server setup
950  *
951  * This routine is called from yyparse() when a Server statment is
952  * found.
953  *
954  * Arguments:
955  *      name    pointer to LIS name
956  *
957  * Returns:
958  *      0       success
959  *      else    error encountered
960  *
961  */
962 int
963 start_server(name)
964         char    *name;
965 {
966         int             i;
967         Scsp_server     *ssp;
968         Scsp_dcs        *dcsp, *next_dcs;
969         Scsp_cse        *csep, *next_cse;
970
971         /*
972          * See if we already have an entry for this name
973          */
974         for (ssp = scsp_server_head; ssp; ssp = ssp->ss_next) {
975                 if (strcasecmp(ssp->ss_name, name) == 0)
976                         break;
977         }
978
979         if (ssp) {
980                 /*
981                  * Log the fact that we're updating the entry
982                  */
983                 scsp_log(LOG_INFO, "updating server entry for %s",
984                                 (void *)name);
985
986                 /*
987                  * Free the existing cache
988                  */
989                 for (i = 0; i < SCSP_HASHSZ; i++) {
990                         for (csep = ssp->ss_cache[i]; csep;
991                                         csep = next_cse) {
992                                 next_cse = csep->sc_next;
993                                 UNLINK(csep, Scsp_cse, ssp->ss_cache[i],
994                                                 sc_next);
995                                 free(csep);
996                         }
997                 }
998
999                 /*
1000                  * Delete existing DCS blocks
1001                  */
1002                 for (dcsp = ssp->ss_dcs; dcsp; dcsp = next_dcs) {
1003                         next_dcs = dcsp->sd_next;
1004                         scsp_dcs_delete(dcsp);
1005                 }
1006         } else {
1007                 /*
1008                  * Get a new server entry
1009                  */
1010                 ssp = calloc(1, sizeof(Scsp_server));
1011                 if (ssp == NULL) {
1012                         scsp_log(LOG_ERR, "unable to allocate server entry");
1013                         exit(1);
1014                 }
1015                 ssp->ss_sock = -1;
1016                 ssp->ss_dcs_lsock = -1;
1017
1018                 /*
1019                  * Set the name
1020                  */
1021                 ssp->ss_name = strdup(name);
1022
1023                 /*
1024                  * Link in the new interface entry
1025                  */
1026                 LINK2TAIL(ssp, Scsp_server, scsp_server_head,
1027                                 ss_next);
1028         }
1029
1030         /*
1031          * If the mark is already set, this is a duplicate command
1032          */
1033         if (ssp->ss_mark) {
1034                 parse_error("duplicate server \"%s\"", name);
1035                 return(1);
1036         }
1037
1038         /*
1039          * Make this the current interface
1040          */
1041         current_server = ssp;
1042
1043         return(0);
1044 }
1045
1046
1047 /*
1048  * Finish up server configuration
1049  *
1050  * This routine is called from yyparse() when the end of a server
1051  * statement is reached.  It checks that required fields are set
1052  * and marks the entry as processed.
1053  *
1054  * Arguments:
1055  *      None
1056  *
1057  * Returns:
1058  *      0       OK
1059  *      1       Error
1060  *
1061  */
1062 int
1063 finish_server()
1064 {
1065         int             rc = 0;
1066         Scsp_server     *ssp;
1067
1068         /*
1069          * Get the current network interface address
1070          */
1071         ssp = current_server;
1072         if (!ssp) {
1073                 parse_error("Server not found");
1074                 rc++;
1075         }
1076
1077         /*
1078          * Mark the interface as processed
1079          */
1080         ssp->ss_mark = 1;
1081
1082         /*
1083          * Make sure the interface has been configured
1084          */
1085         if (ssp->ss_intf == (char *)0) {
1086                 parse_error("netif missing from server specification");
1087                 rc++;
1088         }
1089
1090         /*
1091          * Make sure the protocol is set
1092          */
1093         if (ssp->ss_pid == 0) {
1094                 parse_error("protocol missing from server specification");
1095                 rc++;
1096         }
1097
1098         /*
1099          * Make sure the server group is set
1100          */
1101         if (ssp->ss_sgid == 0) {
1102                 parse_error("server group ID missing from server specification");
1103                 rc++;
1104         }
1105
1106         /*
1107          * Make sure at least one DCS is configured
1108          */
1109         if (ssp->ss_dcs == (Scsp_dcs *)0) {
1110                 parse_error("no DCS configured for server");
1111                 rc++;
1112         }
1113
1114         /*
1115          * Mark the end of the server
1116          */
1117         current_server = (Scsp_server *)0;
1118
1119         return(rc);
1120 }
1121
1122
1123 /*
1124  * Configure log file for SCSP server
1125  *
1126  * This routine is called from yyparse() to process a log File command.
1127  *
1128  * Arguments:
1129  *      file    name of logging file
1130  *
1131  * Returns:
1132  *      0       success
1133  *      1       error encountered
1134  *
1135  */
1136 int
1137 set_log_file(file)
1138         char    *file;
1139 {
1140         /*
1141          * Make sure we haven't already got a log file
1142          */
1143         if (scsp_log_file) {
1144                 parse_error("multiple log files specified");
1145                 return(1);
1146         }
1147
1148         /*
1149          * Open the file
1150          */
1151         scsp_log_file = fopen(file, "a");
1152         if (!scsp_log_file) {
1153                 parse_error("can't open log file");
1154                 return(1);
1155         }
1156
1157         return(0);
1158 }