1 /*
2  * IS-IS Rout(e)ing protocol - isis_circuit.c
3  *
4  * Copyright (C) 2001,2002   Sampo Saaristo
5  *                           Tampere University of Technology
6  *                           Institute of Communications Engineering
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public Licenseas published by the Free
10  * Software Foundation; either version 2 of the License, or (at your option)
11  * any later version.
12  *
13  * This program is distributed in the hope that it will be useful,but WITHOUT
14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
16  * more details.
17 
18  * You should have received a copy of the GNU General Public License along
19  * with this program; if not, write to the Free Software Foundation, Inc.,
20  * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  */
22 
23 #include "pmacct.h"
24 #include "isis.h"
25 
26 #ifndef ETHER_ADDR_LEN
27 #define	ETHER_ADDR_LEN	ETHERADDRL
28 #endif
29 
30 #include "thread.h"
31 #include "hash.h"
32 #include "prefix.h"
33 #include "stream.h"
34 
35 #include "dict.h"
36 #include "iso.h"
37 #include "isis_constants.h"
38 #include "isis_common.h"
39 #include "isis_circuit.h"
40 #include "isis_tlv.h"
41 #include "isis_lsp.h"
42 #include "isis_pdu.h"
43 #include "isis_network.h"
44 #include "isis_misc.h"
45 #include "isis_constants.h"
46 #include "isis_adjacency.h"
47 #include "isis_flags.h"
48 #include "isisd.h"
49 #include "isis_csm.h"
50 #include "isis_events.h"
51 
52 extern struct thread_master *master;
53 extern struct isis *isis;
54 
55 /*
56  * Prototypes.
57  */
58 void isis_circuit_down(struct isis_circuit *);
59 
60 struct isis_circuit *
isis_circuit_new()61 isis_circuit_new ()
62 {
63   struct isis_circuit *circuit;
64   int i;
65 
66   circuit = calloc(1, sizeof (struct isis_circuit));
67   if (circuit)
68     {
69       /* set default metrics for circuit */
70       for (i = 0; i < 2; i++)
71 	{
72 	  circuit->metrics[i].metric_default = DEFAULT_CIRCUIT_METRICS;
73 	  circuit->metrics[i].metric_expense = METRICS_UNSUPPORTED;
74 	  circuit->metrics[i].metric_error = METRICS_UNSUPPORTED;
75 	  circuit->metrics[i].metric_delay = METRICS_UNSUPPORTED;
76 	  circuit->te_metric[i] = DEFAULT_CIRCUIT_METRICS;
77 	}
78     }
79   else
80     {
81       Log(LOG_ERR, "ERROR ( %s/core/ISIS ): Can't calloc isis circuit\n", config.name);
82       return NULL;
83     }
84 
85   return circuit;
86 }
87 
88 void
isis_circuit_configure(struct isis_circuit * circuit,struct isis_area * area)89 isis_circuit_configure (struct isis_circuit *circuit, struct isis_area *area)
90 {
91   int i;
92   circuit->area = area;
93   /*
94    * The level for the circuit is same as for the area, unless configured
95    * otherwise.
96    */
97   circuit->circuit_is_type = area->is_type;
98   /*
99    * Default values
100    */
101   for (i = 0; i < 2; i++)
102     {
103       circuit->hello_interval[i] = HELLO_INTERVAL;
104       circuit->hello_multiplier[i] = HELLO_MULTIPLIER;
105       circuit->csnp_interval[i] = CSNP_INTERVAL;
106       circuit->psnp_interval[i] = PSNP_INTERVAL;
107       circuit->u.bc.priority[i] = DEFAULT_PRIORITY;
108     }
109   if (circuit->circ_type == CIRCUIT_T_BROADCAST)
110     {
111       circuit->u.bc.adjdb[0] = pm_list_new ();
112       circuit->u.bc.adjdb[1] = pm_list_new ();
113       circuit->u.bc.pad_hellos = 1;
114     }
115   circuit->lsp_interval = LSP_INTERVAL;
116 
117   /*
118    * Add the circuit into area
119    */
120   pm_listnode_add (area->circuit_list, circuit);
121 
122   circuit->idx = flags_get_index (&area->flags);
123   circuit->lsp_queue = pm_list_new ();
124 
125   return;
126 }
127 
128 void
isis_circuit_deconfigure(struct isis_circuit * circuit,struct isis_area * area)129 isis_circuit_deconfigure (struct isis_circuit *circuit,
130 			  struct isis_area *area)
131 {
132 
133   /* destroy adjacencies */
134   if (circuit->u.bc.adjdb[0])
135     isis_adjdb_iterate (circuit->u.bc.adjdb[0], (void(*) (struct isis_adjacency *, void *)) isis_delete_adj, circuit->u.bc.adjdb[0]);
136   if (circuit->u.bc.adjdb[1])
137     isis_adjdb_iterate (circuit->u.bc.adjdb[1], (void(*) (struct isis_adjacency *, void *)) isis_delete_adj, circuit->u.bc.adjdb[1]);
138   /* Remove circuit from area */
139   pm_listnode_delete (area->circuit_list, circuit);
140   /* Free the index of SRM and SSN flags */
141   flags_free_index (&area->flags, circuit->idx);
142 
143   return;
144 }
145 
146 void
isis_circuit_del(struct isis_circuit * circuit)147 isis_circuit_del (struct isis_circuit *circuit)
148 {
149 
150   if (!circuit)
151     return;
152 
153   if (circuit->circ_type == CIRCUIT_T_BROADCAST)
154     {
155       /* destroy adjacency databases */
156       if (circuit->u.bc.adjdb[0])
157 	pm_list_delete (circuit->u.bc.adjdb[0]);
158       if (circuit->u.bc.adjdb[1])
159 	pm_list_delete (circuit->u.bc.adjdb[1]);
160       /* destroy neighbour lists */
161       if (circuit->u.bc.lan_neighs[0])
162 	pm_list_delete (circuit->u.bc.lan_neighs[0]);
163       if (circuit->u.bc.lan_neighs[1])
164 	pm_list_delete (circuit->u.bc.lan_neighs[1]);
165       /* destroy addresses */
166     }
167   if (circuit->ip_addrs)
168     pm_list_delete (circuit->ip_addrs);
169   if (circuit->ipv6_link)
170     pm_list_delete (circuit->ipv6_link);
171   if (circuit->ipv6_non_link)
172     pm_list_delete (circuit->ipv6_non_link);
173 
174   /* and lastly the circuit itself */
175   free(circuit);
176 
177   return;
178 }
179 
180 void
isis_circuit_up(struct isis_circuit * circuit)181 isis_circuit_up (struct isis_circuit *circuit)
182 {
183   if (circuit->circ_type == CIRCUIT_T_P2P)
184     {
185       /* initializing the hello send threads
186        * for a ptp IF
187        */
188       thread_add_event (master, send_p2p_hello, circuit, 0);
189     }
190 
191   /* if needed, initialize the circuit streams (most likely not) */
192   if (circuit->rcv_stream == NULL)
193     circuit->rcv_stream = stream_new (ISO_MTU (circuit));
194 
195   if (circuit->snd_stream == NULL)
196     circuit->snd_stream = stream_new (ISO_MTU (circuit));
197 
198   // isis_sock_init (circuit);
199 
200   // THREAD_TIMER_ON (master, circuit->t_read, isis_receive, circuit, circuit->fd);
201 }
202 
203 void
isis_circuit_down(struct isis_circuit * circuit)204 isis_circuit_down (struct isis_circuit *circuit)
205 {
206   /* Cancel all active threads -- FIXME: wrong place */
207   /* HT: Read thread if GNU_LINUX, TIMER thread otherwise. */
208   THREAD_OFF (circuit->t_read);
209   if (circuit->circ_type == CIRCUIT_T_BROADCAST)
210     {
211       THREAD_TIMER_OFF (circuit->u.bc.t_send_lan_hello[0]);
212       THREAD_TIMER_OFF (circuit->u.bc.t_send_lan_hello[1]);
213       THREAD_TIMER_OFF (circuit->u.bc.t_run_dr[0]);
214       THREAD_TIMER_OFF (circuit->u.bc.t_run_dr[1]);
215     }
216   else if (circuit->circ_type == CIRCUIT_T_P2P)
217     {
218       THREAD_TIMER_OFF (circuit->u.p2p.t_send_p2p_hello);
219     }
220 
221   if (circuit->t_send_psnp[0]) {
222     THREAD_TIMER_OFF (circuit->t_send_psnp[0]);
223   }
224   if (circuit->t_send_psnp[1]) {
225     THREAD_TIMER_OFF (circuit->t_send_psnp[1]);
226   }
227   /* close the socket */
228   close (circuit->fd);
229 
230   return;
231 }
232 
233 void
circuit_update_nlpids(struct isis_circuit * circuit)234 circuit_update_nlpids (struct isis_circuit *circuit)
235 {
236   circuit->nlpids.count = 0;
237 
238   if (circuit->ip_router)
239     {
240       circuit->nlpids.nlpids[0] = NLPID_IP;
241       circuit->nlpids.count++;
242     }
243   if (circuit->ipv6_router)
244     {
245       circuit->nlpids.nlpids[circuit->nlpids.count] = NLPID_IPV6;
246       circuit->nlpids.count++;
247     }
248   return;
249 }
250