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