Annotation of embedaddon/freevrrpd/vrrp_state.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (c) 2001,2002 Sebastien Petit <spe@bsdfr.org>
3: *
4: * Redistribution and use in source forms, with and without modification,
5: * are permitted provided that the following conditions are met:
6: * 1. Redistributions of source code must retain the above copyright notice,
7: * this list of conditions and the following disclaimer.
8: * 2. Redistributions in binary form must reproduce the above copyright notice,
9: * this list of conditions and the following disclaimer in the documentation
10: * and/or other materials provided with the distribution. Obviously, it
11: * would be nice if you gave credit where credit is due but requiring it
12: * would be too onerous.
13: * 3. All advertising materials mentioning features or use of this software
14: * must display the following acknowledgement:
15: * This product includes software developed by Sebastien Petit.
16: * 4. Neither the name of its contributors may be used to endorse or promote
17: * products derived from this software without specific prior written
18: * permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30: * SUCH DAMAGE.
31: *
32: * $Id: vrrp_state.c,v 1.18 2004/04/02 11:04:46 spe Exp $
33: */
34:
35: #include <stdlib.h>
36: #include <errno.h>
37: #include "vrrp_state.h"
38: #ifdef ENABLE_VRRP_AH
39: #include "vrrp_ah.h"
40: #endif
41:
42: char
43: vrrp_state_initialize(struct vrrp_vr * vr)
44: {
45: if ((vr->priority == 255) && (! vr->fault)) {
46: if (vrrp_state_set_master(vr) == -1)
47: return -1;
48: } else if (vrrp_state_set_backup(vr) == -1)
49: return -1;
50:
51: return 0;
52: }
53:
54: char
55: vrrp_state_set_master(struct vrrp_vr * vr)
56: {
57: int returnCode = 0;
58: int counter = 0;
59:
60: vrrp_network_send_advertisement(vr);
61: vrrp_thread_mutex_lock();
62: vrrp_thread_mutex_lock_monitor();
63: if (vrrp_interface_vripaddr_set(vr) == -1) {
64: vrrp_thread_mutex_unlock_monitor();
65: vrrp_thread_mutex_unlock();
66: return -1;
67: }
68: if (vrrp_interface_up(vr->viface_name) < 0) {
69: vrrp_thread_mutex_unlock_monitor();
70: vrrp_thread_mutex_unlock();
71: return -1;
72: }
73:
74: /* Some NICs will reset (eg: bge/em) and wait some seconds before becoming carrier again */
75: /* So we must wait for carrier */
76: if (vr->useMonitoredCircuits) {
77: for (counter = 0; (counter < vr->vr_if->carrier_timeout) && (returnCode != 1); counter++) {
78: returnCode = vrrp_moncircuit_interface_status(vr->sd, vr->vr_if->if_name);
79: sleep(1);
80: }
81: }
82:
83: vrrp_thread_mutex_unlock_monitor();
84: vrrp_thread_mutex_unlock();
85: if (vr->spanningTreeLatency) {
86: syslog(LOG_NOTICE, "waiting %d seconds for the spanning tree latency", vr->spanningTreeLatency);
87: sleep(vr->spanningTreeLatency);
88: }
89: if (vrrp_misc_calcul_tminterval(&vr->tm.adv_tm, vr->adv_int) == -1)
90: return -1;
91: vr->state = VRRP_STATE_MASTER;
92: syslog(LOG_NOTICE, "server state vrid %d: master", vr->vr_id);
93: printf("server state vrid %d: master\n", vr->vr_id);
94: if (vr->master_script) {
95: syslog(LOG_INFO, "[master] executing script %s\n", vr->master_script);
96: if (system(vr->master_script) == -1)
97: syslog(LOG_ERR, "[master] cannot execute script %s\n", vr->master_script);
98: else
99: syslog(LOG_INFO, "[master] script %s has been executed\n", vr->master_script);
100: }
101:
102: return 0;
103: }
104:
105: char
106: vrrp_state_set_backup(struct vrrp_vr * vr)
107: {
108: int returnCode = 0;
109: int counter = 0;
110:
111: vrrp_thread_mutex_lock();
112: vrrp_interface_vripaddr_delete(vr);
113: vrrp_thread_mutex_lock_monitor();
114: if (vrrp_interface_down(vr->viface_name) < 0) {
115: vrrp_thread_mutex_unlock_monitor();
116: vrrp_thread_mutex_unlock();
117: return -1;
118: }
119:
120: /* Some NICs will reset (eg: bge/em) and wait some seconds before becoming carrier again */
121: /* So we must wait for carrier */
122: if (vr->useMonitoredCircuits) {
123: for (counter = 0; (counter < vr->vr_if->carrier_timeout) && (returnCode != 1); counter++) {
124: returnCode = vrrp_moncircuit_interface_status(vr->sd, vr->vr_if->if_name);
125: sleep(1);
126: }
127: }
128: vrrp_thread_mutex_unlock_monitor();
129: vrrp_thread_mutex_unlock();
130: if (vr->spanningTreeLatency) {
131: syslog(LOG_NOTICE, "waiting %d seconds for the spanning tree latency", vr->spanningTreeLatency);
132: sleep(vr->spanningTreeLatency);
133: }
134: vr->skew_time = (256 - vr->priority) / 256;
135: vr->master_down_int = (3 * vr->adv_int) + vr->skew_time;
136: if (vrrp_misc_calcul_tminterval(&vr->tm.master_down_tm, vr->master_down_int) == -1)
137: return -1;
138: vr->state = VRRP_STATE_BACKUP;
139: syslog(LOG_NOTICE, "server state vrid %d: backup", vr->vr_id);
140: printf("server state vrid %d: backup\n", vr->vr_id);
141: if (vr->backup_script) {
142: syslog(LOG_INFO, "[backup] executing script %s\n", vr->backup_script);
143: if (system(vr->backup_script) == -1)
144: syslog(LOG_ERR, "[backup] cannot execute script %s\n", vr->backup_script);
145: else
146: syslog(LOG_INFO, "[backup] script %s has been executed\n", vr->backup_script);
147: }
148:
149: return 0;
150: }
151:
152: char
153: vrrp_state_select(struct vrrp_vr * vr, struct timeval * interval)
154: {
155: int coderet;
156: fd_set readfds;
157:
158: FD_ZERO(&readfds);
159: FD_SET(vr->sd, &readfds);
160: coderet = select(FD_SETSIZE, &readfds, NULL, NULL, interval);
161:
162: return coderet;
163: }
164:
165: /* Operation a effectuer durant l'etat master */
166: char
167: vrrp_state_master(struct vrrp_vr * vr)
168: {
169: int coderet;
170: u_char packet[4096];
171: ssize_t packetSize;
172: struct ip *ipp = (struct ip *) packet;
173: #ifdef ENABLE_VRRP_AH
174: struct vrrp_hdr *vrrph = (struct vrrp_hdr *) & packet[sizeof(struct ip)+vrrp_ah_ahhdr_len(vr)];
175: #else
176: struct vrrp_hdr *vrrph = (struct vrrp_hdr *) & packet[sizeof(struct ip)];
177: #endif
178: struct timeval interval;
179: struct sockaddr_in saddr;
180: socklen_t len;
181:
182: for (;;) {
183: if (vrrp_misc_calcul_tmrelease(&vr->tm.adv_tm, &interval) == -1)
184: return -1;
185: coderet = vrrp_state_select(vr, &interval);
186: if (coderet > 0) {
187: len = sizeof(struct sockaddr_in);
188: packetSize = recvfrom(vr->sd, packet, sizeof(packet), 0, (struct sockaddr *)&saddr, &len);
189: if (packetSize == -1) {
190: syslog(LOG_ERR, "can't read on vr->sd socket descriptor: %s", strerror(errno));
191: return -1;
192: }
193: if (vrrp_misc_check_vrrp_packet(vr, packet, packetSize) == -1)
194: continue;
195: if (vrrph->priority == 0) {
196: if (vr->sd == -1)
197: return -1;
198: vrrp_network_send_advertisement(vr);
199: if (vrrp_misc_calcul_tminterval(&vr->tm.adv_tm, vr->adv_int) == -1)
200: return -1;
201: continue;
202: }
203: if (vrrp_state_check_priority(vrrph, vr, ipp->ip_src) || (vr->fault) || (vr->vr_if->alive != 1)) {
204: if (vrrp_state_set_backup(vr) == -1)
205: return -1;
206: }
207: return 0;
208: }
209: if (coderet == 0) {
210: if ((vr->vr_if->alive != 1) || (vr->fault)) {
211: if (vrrp_state_set_backup(vr) == -1)
212: return -1;
213: return 0;
214: }
215: vrrp_network_send_advertisement(vr);
216: if (vrrp_misc_calcul_tminterval(&vr->tm.adv_tm, vr->adv_int) == -1)
217: return -1;
218: continue;
219: }
220: if (coderet == -1) {
221: syslog(LOG_ERR, "select on readfds fd_set failed: %s", strerror(errno));
222: return -1;
223: }
224: }
225:
226: /* Normally never executed */
227: return 0;
228: }
229:
230: char
231: vrrp_state_backup(struct vrrp_vr * vr)
232: {
233: int coderet;
234: u_char packet[4096];
235: ssize_t packetSize;
236: #ifdef ENABLE_VRRP_AH
237: struct vrrp_hdr *vrrph = (struct vrrp_hdr *) & packet[sizeof(struct ip)+vrrp_ah_ahhdr_len(vr)];
238: #else
239: struct vrrp_hdr *vrrph = (struct vrrp_hdr *) & packet[sizeof(struct ip)];
240: #endif
241: struct timeval interval;
242: struct sockaddr_in saddr;
243: socklen_t len;
244:
245: for (;;) {
246: if (vrrp_misc_calcul_tmrelease(&vr->tm.master_down_tm, &interval) == -1)
247: return -1;
248: coderet = vrrp_state_select(vr, &interval);
249: if (coderet > 0) {
250: len = sizeof(struct sockaddr_in);
251: packetSize = recvfrom(vr->sd, packet, sizeof(packet), 0, (struct sockaddr *)&saddr, &len);
252: if (packetSize == -1) {
253: syslog(LOG_ERR, "can't read on vr->sd socket descriptor: %s", strerror(errno));
254: return -1;
255: }
256: if (vrrp_misc_check_vrrp_packet(vr, packet, packetSize) == -1)
257: continue;
258: if (vrrph->priority == 0) {
259: if (vrrp_misc_calcul_tminterval(&vr->tm.master_down_tm, vr->skew_time) == -1)
260: return -1;
261: continue;
262: }
263: if (vr->preempt_mode == 0 || vrrph->priority >= vr->priority)
264: if (vrrp_misc_calcul_tminterval(&vr->tm.master_down_tm, vr->master_down_int) == -1)
265: return -1;
266: continue;
267: }
268: if (coderet == -1) {
269: syslog(LOG_ERR, "select on readfds fd_set failed: %s", strerror(errno));
270: return -1;
271: }
272: if ((! coderet) && (vr->vr_if->alive == 1) && (! vr->fault)) {
273: if (! vrrp_state_set_master(vr))
274: return 0;
275: }
276: else
277: if (vrrp_misc_calcul_tminterval(&vr->tm.master_down_tm, vr->master_down_int) == -1)
278: return -1;
279: }
280:
281: /* Normally never executed */
282: return 0;
283: }
284:
285: char
286: vrrp_state_check_priority(struct vrrp_hdr * vrrph, struct vrrp_vr * vr, struct in_addr addr)
287: {
288: if (vrrph->priority > vr->priority)
289: return 1;
290: if ((vrrph->priority == vr->priority) && (addr.s_addr > vr->vr_if->ip_addrs[0].s_addr))
291: return 1;
292:
293: return 0;
294: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>