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