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