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