Annotation of embedaddon/freevrrpd/vrrp_misc.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_misc.c,v 1.8 2004/04/04 19:45:46 rival Exp $
33: */
34:
35: #include <errno.h>
36: #include "vrrp_misc.h"
37: #ifdef ENABLE_VRRP_AH
38: #include "vrrp_ah.h"
39: #endif
40:
41: /* this code is based on ifconfig.c */
42: #define ROUNDUP(a) \
43: ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
44: #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
45:
46: void
47: rt_xaddrs(caddr_t cp, caddr_t cplim, struct rt_addrinfo * rtinfo)
48: {
49: struct sockaddr *sa;
50: int i;
51:
52: memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info));
53: for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
54: if ((rtinfo->rti_addrs & (1 << i)) == 0)
55: continue;
56: rtinfo->rti_info[i] = sa = (struct sockaddr *) cp;
57: ADVANCE(cp, sa);
58: }
59: }
60:
61: char
62: vrrp_misc_get_if_infos(char *if_name, struct ether_addr * ethaddr, struct in_addr * ip_addrs, int *size)
63: {
64: int addrcount;
65: struct if_msghdr *ifm, *nextifm;
66: struct ifa_msghdr *ifam;
67: struct sockaddr_dl *sdl;
68: struct sockaddr_in *sin;
69: char *buf, *lim, *next;
70: char name[64];
71: struct rt_addrinfo info;
72: size_t needed;
73: int mib[6];
74: int sizes = *size;
75: char myinterface = 0;
76:
77: mib[0] = CTL_NET;
78: mib[1] = PF_ROUTE;
79: mib[2] = 0;
80: mib[3] = AF_INET;
81: mib[4] = NET_RT_IFLIST;
82: mib[5] = 0;
83:
84: if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
85: syslog(LOG_ERR, "iflist-sysctl-estimate: %s", strerror(errno));
86: return -1;
87: }
88: if ((buf = malloc(needed)) == NULL) {
89: syslog(LOG_ERR, "malloc: %s", strerror(errno));
90: return -1;
91: }
92: if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
93: syslog(LOG_ERR, "actual retrieval of interface table: %s", strerror(errno));
94: free(buf);
95: return -1;
96: }
97: lim = buf + needed;
98:
99: next = buf;
100: while (next < lim) {
101: *size = sizes;
102: ifm = (struct if_msghdr *) next;
103: if (ifm->ifm_type == RTM_IFINFO) {
104: sdl = (struct sockaddr_dl *) (ifm + 1);
105: strncpy(name, sdl->sdl_data, sdl->sdl_nlen);
106: name[sdl->sdl_nlen] = '\0';
107: } else {
108: syslog(LOG_ERR, "there is an error: ifm->ifm_type != RTM_INFO");
109: free(buf);
110: return -1;
111: }
112: if (strlen(name) != sdl->sdl_nlen)
113: continue;
114: if (strncmp(name, sdl->sdl_data, sdl->sdl_nlen) != 0)
115: continue;
116: myinterface = (sdl->sdl_nlen == strlen(if_name)) && (!strncmp(if_name, sdl->sdl_data, sdl->sdl_nlen));
117: if (ip_addrs != NULL && size != NULL && *size > 0) {
118: next += ifm->ifm_msglen;
119: ifam = NULL;
120: addrcount = 0;
121: while (next < lim) {
122: nextifm = (struct if_msghdr *) next;
123: if (nextifm->ifm_type != RTM_NEWADDR)
124: break;
125: ifam = (struct ifa_msghdr *) nextifm;
126: info.rti_addrs = ifam->ifam_addrs;
127: rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam, &info);
128: sin = (struct sockaddr_in *) info.rti_info[RTAX_IFA];
129: if (myinterface)
130: ip_addrs[addrcount] = sin->sin_addr;
131: addrcount++;
132: if (*size <= addrcount)
133: break;
134: next += nextifm->ifm_msglen;
135: }
136: *size = addrcount;
137: }
138: if (ethaddr != NULL)
139: if (myinterface)
140: bcopy(LLADDR(sdl), ethaddr, sizeof(struct ether_addr));
141: if (myinterface)
142: break;
143: }
144: free(buf);
145: return 0;
146: }
147:
148: char
149: vrrp_misc_get_vlan_infos(struct vrrp_vr *vr)
150: {
151: struct sockaddr_dl *sdl;
152: struct if_msghdr *ifm;
153: char *buf, *lim, *next;
154: char name[64];
155: size_t needed;
156: int mib[6];
157:
158: if (! vr) {
159: syslog(LOG_ERR, "vr is NULL. cannot vrrp_misc_get_vlan_infos");
160: return -1;
161: }
162: mib[0] = CTL_NET;
163: mib[1] = PF_ROUTE;
164: mib[2] = 0;
165: mib[3] = AF_INET;
166: mib[4] = NET_RT_IFLIST;
167: mib[5] = 0;
168:
169: if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
170: syslog(LOG_ERR, "iflist-sysctl-estimate: %s", strerror(errno));
171: return -1;
172: }
173: if ((buf = malloc(needed)) == NULL) {
174: syslog(LOG_ERR, "malloc: %s", strerror(errno));
175: return -1;
176: }
177: if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
178: syslog(LOG_ERR, "actual retrieval of interface table: %s", strerror(errno));
179: free(buf);
180: return -1;
181: }
182: lim = buf + needed;
183:
184: next = buf;
185: while (next < lim) {
186: ifm = (struct if_msghdr *) next;
187: if (ifm->ifm_type == RTM_IFINFO) {
188: sdl = (struct sockaddr_dl *) (ifm + 1);
189: strncpy(name, sdl->sdl_data, sdl->sdl_nlen);
190: name[sdl->sdl_nlen] = '\0';
191: if (! bcmp(LLADDR(sdl), &vr->vr_if->ethaddr, sizeof(struct ether_addr))) {
192: vrrp_vlanlist_add(vr, name);
193: }
194: }
195: else
196: if (ifm->ifm_type != RTM_NEWADDR) {
197: syslog(LOG_ERR, "there is an error: ifm->ifm_type != RTM_INFO");
198: free(buf);
199: return -1;
200: }
201: next += ifm->ifm_msglen;
202: }
203: free(buf);
204: return 0;
205: }
206: int
207: vrrp_misc_get_priority(struct vrrp_vr * vr)
208: {
209: u_char i = 0, j = 0;
210:
211: if (vr->cnt_ip == vr->vr_if->nb_ip) {
212: while (j < vr->cnt_ip) {
213: while (i < vr->vr_if->nb_ip) {
214: if (vr->vr_if->ip_addrs[j].s_addr == vr->vr_ip[i].addr.s_addr)
215: break;
216: i++;
217: }
218: if (i >= vr->vr_if->nb_ip)
219: return VRRP_PRIORITY_DEFAULT;
220: j++;
221: }
222: return VRRP_PRIORITY_MASTER;
223: } else
224: return VRRP_PRIORITY_DEFAULT;
225: }
226:
227: u_short
228: vrrp_misc_compute_checksum(u_short * addr, register int len)
229: {
230: int nleft = len;
231: const u_short * w = addr;
232: u_short answer;
233: int sum = 0;
234:
235: while (nleft > 1) {
236: sum += *w++;
237: nleft -= 2;
238: }
239: if (nleft == 1)
240: sum += htons(*(u_char *) w << 8);
241: sum = (sum >> 16) + (sum & 0xFFFF);
242: sum += (sum >> 16);
243: answer = ~sum;
244:
245: return answer;
246: }
247:
248: char
249: vrrp_misc_calcul_tminterval(struct timeval * timer, u_int interval)
250: {
251: struct timeval tm;
252:
253: if (gettimeofday(&tm, NULL) == -1) {
254: syslog(LOG_ERR, "cannot get time with gettimeofday: %s", strerror(errno));
255: return -1;
256: }
257: timer->tv_sec = tm.tv_sec + interval;
258: timer->tv_usec = tm.tv_usec;
259:
260: return 0;
261: }
262:
263: char
264: vrrp_misc_calcul_tmrelease(struct timeval * timer, struct timeval * interval)
265: {
266: struct timeval tm;
267:
268: interval->tv_sec = 0;
269: interval->tv_usec = 0;
270: if (gettimeofday(&tm, NULL) == -1) {
271: syslog(LOG_ERR, "cannot get time with gettimeofday: %s", strerror(errno));
272: return -1;
273: }
274: if (tm.tv_sec < timer->tv_sec || (tm.tv_sec == timer->tv_sec && tm.tv_usec < timer->tv_usec)) {
275: interval->tv_sec = timer->tv_sec - tm.tv_sec;
276: if (timer->tv_usec < tm.tv_usec) {
277: interval->tv_sec--;
278: interval->tv_usec = (timer->tv_usec + 1000000) - tm.tv_usec;
279: } else
280: interval->tv_usec = timer->tv_usec - tm.tv_usec;
281: }
282: return 0;
283: }
284:
285: u_short
286: vrrp_misc_vphdr_len(struct vrrp_hdr * vph)
287: {
288: return (sizeof(struct vrrp_hdr) + (vph->cnt_ip << 2) + VRRP_AUTH_DATA_LEN);
289: }
290:
291: char
292: vrrp_misc_check_vrrp_packet(struct vrrp_vr * vr, char *packet, ssize_t packetSize)
293: {
294: struct ip *iph = (struct ip *) packet;
295: #ifdef ENABLE_VRRP_AH
296: struct vrrp_hdr *vph = (struct vrrp_hdr *) & packet[sizeof(struct ip)+vrrp_ah_ahhdr_len(vr)];
297: #else
298: struct vrrp_hdr *vph = (struct vrrp_hdr *) & packet[sizeof(struct ip)];
299: #endif
300: struct in_addr *ip_addrs = (struct in_addr *) & packet[sizeof(struct ip) + sizeof(struct vrrp_hdr)];
301: char *password = NULL;
302: int error = 0;
303: int cpt, cpt2;
304: char detected;
305: u_short checksum_orig = vph->csum;
306:
307: if (iph->ip_ttl != VRRP_MULTICAST_TTL) {
308: syslog(LOG_ERR, "ip ttl of vrrp packet isn't set to 255. Packet is discarded !");
309: return -1;
310: }
311: if (vph->vrrp_v != VRRP_PROTOCOL_VERSION) {
312: syslog(LOG_ERR, "vrrp version of vrrp packet is not valid or compatible with this daemon. Packet is discarded !");
313: return -1;
314: }
315: if (packetSize < sizeof(struct ip) + vrrp_misc_vphdr_len(vph)) {
316: syslog(LOG_ERR, "invalid vrrp packet received (invalid size). Packet is discarded !");
317: return -1;
318: }
319: vph->csum = 0;
320: if (vrrp_misc_compute_checksum((u_short *) vph, vrrp_misc_vphdr_len(vph)) != checksum_orig) {
321: syslog(LOG_ERR, "checksum of vrrp packet is invalid. Packet is discarded !");
322: return -1;
323: }
324: vph->csum = checksum_orig;
325: if (vph->vr_id != vr->vr_id)
326: return -1;
327: if (vph->cnt_ip != vr->cnt_ip)
328: error = 1;
329: else {
330: for (cpt = 0; cpt < vph->cnt_ip; cpt++) {
331: detected = 0;
332: for (cpt2 = 0; cpt2 < vr->cnt_ip; cpt2++) {
333: if (ip_addrs[cpt].s_addr == vr->vr_ip[cpt2].addr.s_addr)
334: detected = 1;
335: }
336: if (! detected) {
337: syslog(LOG_ERR, "error to 1 because not detected");
338: error = 1;
339: break;
340: }
341: }
342: }
343: if (error == 1) {
344: syslog(LOG_ERR, "detection of misconfigured server on the network for vrid = %u and priority = %u", vph->vr_id, vph->priority);
345: if (vph->priority != VRRP_PRIORITY_MASTER) {
346: syslog(LOG_ERR, "this server is not a master virtual router. Packet is discarded !");
347: return -1;
348: }
349: }
350: if (vph->adv_int != vr->adv_int) {
351: syslog(LOG_ERR, "the advertisement interval set on received vrrp packet isn't same localy. Packet is discarded !");
352: return -1;
353: }
354: #ifdef ENABLE_VRRP_AH
355: /* checking function */
356: vrrp_ah_check_ahhdr(packet,vr);
357: #endif
358: /* Verification of Authentification */
359: password = (char *)&ip_addrs[vph->cnt_ip];
360: if (vr->auth_type == 1 && strncmp(vr->password, password, 8)) {
361: syslog(LOG_ERR, "authentification incorrect in a received vrrp packet. Packet is discarded !");
362: return -1;
363: }
364: return 0;
365: }
366:
367: void
368: vrrp_misc_quit(int coderet)
369: {
370: exit(coderet);
371: }
372:
373: struct vrrp_if *
374: vrrp_misc_search_if_entry(char *name)
375: {
376: int cpt = 0;
377:
378: while (cpt < VRRP_PROTOCOL_MAX_VRID) {
379: if (vr_ptr[cpt] == NULL)
380: break;
381: if (!strncmp(vr_ptr[cpt]->vr_if->if_name, name, strlen(name)))
382: return vr_ptr[cpt]->vr_if;
383: cpt++;
384: }
385:
386: return NULL;
387: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>