Annotation of embedaddon/freevrrpd/vrrp_network.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_network.c,v 1.27 2004/04/04 19:45:46 rival Exp $
33: */
34:
35: #include <errno.h>
36: #include <sys/param.h>
37: #include "vrrp_network.h"
38: #include "vrrp_ah.h"
39:
40: u_short ip_id;
41:
42: /* Initialisation pour l'identification IP */
43: void
44: vrrp_network_initialize(void)
45: {
46: srand(time(NULL));
47: ip_id = random() % 65535;
48:
49: return;
50: }
51:
52: /* Open VRRP socket for reading */
53: char
54: vrrp_network_open_socket(struct vrrp_vr * vr)
55: {
56: struct timeval timeout;
57: int hincl = 1;
58:
59: vr->sd = socket(AF_INET, SOCK_RAW, IPPROTO_VRRP);
60: if (vr->sd == -1) {
61: syslog(LOG_ERR, "cannot open raw socket for VRRP protocol [ AF_INET, SOCK_RAW, IPPROTO_VRRP ]: %s", strerror(errno));
62: return -1;
63: }
64: if (setsockopt(vr->sd, IPPROTO_IP, IP_HDRINCL, &hincl, sizeof(hincl))) {
65: syslog(LOG_ERR, "cannot set IP_HDRINCL option on the IPPROTO_IP raw socket: %s", strerror(errno));
66: return -1;
67: }
68: timeout.tv_sec = 0;
69: timeout.tv_usec = 100000;
70: if (setsockopt(vr->sd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) == -1) {
71: syslog(LOG_ERR, "cannot set SO_RCVTIMEO option on the IPPROTO_VRRP raw socket: %s", strerror(errno));
72: return -1;
73: }
74:
75: return 0;
76: }
77:
78: ssize_t
79: vrrp_network_send_packet(char *buffer, int sizebuf, int sd, int log)
80: {
81: struct sockaddr_in addr;
82: ssize_t octets;
83:
84: addr.sin_family = AF_INET;
85: addr.sin_port = 0;
86: addr.sin_len = sizeof(struct sockaddr_in);
87: addr.sin_addr.s_addr = inet_addr(VRRP_MULTICAST_IP);
88: octets = sendto(sd, buffer, sizebuf, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
89: if (octets < 0) {
90: if (log)
91: syslog(LOG_ERR, "can't write to socket: %s", strerror(errno));
92: return -1;
93: }
94:
95: return octets;
96: }
97:
98: u_int
99: vrrp_network_vrrphdr_len(struct vrrp_vr * vr)
100: {
101: u_int len = sizeof(struct vrrp_hdr);
102:
103: len += (vr->cnt_ip << 2) + VRRP_AUTH_DATA_LEN;
104:
105: return len;
106: }
107:
108: void
109: vrrp_network_init_iphdr(char *buffer, struct vrrp_vr * vr)
110: {
111: struct ip *iph = (struct ip *)buffer;
112:
113: iph->ip_hl = 5;
114: iph->ip_v = 4;
115: iph->ip_tos = 0;
116: #if (defined(__FreeBSD__) && (__FreeBSD_version < 1100030)) || defined(__NetBSD__)
117: iph->ip_len = sizeof(struct ip) + vrrp_network_vrrphdr_len(vr) + vrrp_ah_ahhdr_len(vr);
118: #else
119: iph->ip_len = htons(sizeof(struct ip) + vrrp_network_vrrphdr_len(vr) + vrrp_ah_ahhdr_len(vr));
120: #endif
121: /* iph->ip_id = ++ip_id; */
122: iph->ip_off = 0;
123: iph->ip_ttl = VRRP_MULTICAST_TTL;
124: #ifdef ENABLE_VRRP_AH
125: if (vr->AHencryption == 1)
126: iph->ip_p = IPPROTO_AH;
127: else
128: iph->ip_p = IPPROTO_VRRP;
129: #else
130: iph->ip_p = IPPROTO_VRRP;
131: #endif
132: iph->ip_src.s_addr = vr->vr_if->ip_addrs[0].s_addr;
133: iph->ip_dst.s_addr = inet_addr(VRRP_MULTICAST_IP);
134: iph->ip_sum = vrrp_misc_compute_checksum((u_short *) iph, iph->ip_hl << 2);
135:
136: return;
137: }
138:
139: void
140: vrrp_network_init_vrrphdr(char *buffer, struct vrrp_vr * vr)
141: {
142: struct vrrp_hdr *vp;
143: struct in_addr *addr;
144: char *password;
145: int cpt;
146:
147: vp = (struct vrrp_hdr *)buffer;
148: vp->vrrp_v = VRRP_PROTOCOL_VERSION;
149: vp->vrrp_t = VRRP_PROTOCOL_ADVERTISEMENT;
150: vp->vr_id = vr->vr_id;
151: vp->priority = vr->priority;
152: vp->cnt_ip = vr->cnt_ip;
153: vp->auth_type = vr->auth_type;
154: vp->adv_int = vr->adv_int;
155: addr = (struct in_addr *) & buffer[sizeof(struct vrrp_hdr)];
156: for (cpt = 0; cpt < vr->cnt_ip; cpt++) {
157: addr[cpt].s_addr = vr->vr_ip[cpt].addr.s_addr;
158: }
159: if (vr->auth_type == 1) {
160: password = (char *)&addr[vr->cnt_ip];
161: strncpy(password, vr->password, 8);
162: }
163: vp->csum = vrrp_misc_compute_checksum((u_short *) vp, vrrp_network_vrrphdr_len(vr));
164:
165: return;
166: }
167:
168: char
169: vrrp_network_send_advertisement(struct vrrp_vr * vr)
170: {
171: u_char *buffer;
172: #ifdef ENABLE_VRRP_AH
173: u_int len = sizeof(struct ip) + vrrp_ah_ahhdr_len(vr) + vrrp_network_vrrphdr_len(vr);
174: #else
175: u_int len = sizeof(struct ip) + vrrp_network_vrrphdr_len(vr);
176: #endif
177: ssize_t bytes = 0;
178:
179: buffer = (u_char *) malloc(len);
180: bzero(buffer, len);
181:
182: vrrp_network_init_iphdr(buffer, vr);
183: #ifdef ENABLE_VRRP_AH
184: /* add AH adding code */
185: if (vr->AHencryption == 1) {
186: vrrp_ah_init_ahhdr(buffer,vr);
187: vrrp_network_init_vrrphdr(&buffer[sizeof(struct ip)+vrrp_ah_ahhdr_len(vr)], vr);
188: vrrp_ah_hmacmd5(buffer,vr);
189: } else
190: vrrp_network_init_vrrphdr(&buffer[sizeof(struct ip)+vrrp_ah_ahhdr_len(vr)], vr);
191: #else
192: vrrp_network_init_vrrphdr(&buffer[sizeof(struct ip)], vr);
193: #endif
194:
195: if (vr->fault)
196: bytes = vrrp_network_send_packet(buffer, len, vr->sd, 0);
197: else
198: bytes = vrrp_network_send_packet(buffer, len, vr->sd, 1);
199:
200: if (bytes < 0) {
201: syslog(LOG_ERR, "There is a big problem here !");
202: vr->fault = 1;
203: free(buffer);
204: return -1;
205: }
206: vr->fault = 0;
207: free(buffer);
208:
209: return 0;
210: }
211:
212: int
213: vrrp_network_open_bpf(char *if_name)
214: {
215: struct ifreq ifr;
216: int n = 0;
217: char device[16];
218: int sd = 0;
219: int yes = 1;
220:
221: while ((sd <= 0) && (n < 100)) {
222: snprintf(device, sizeof(device), "/dev/bpf%d", n++);
223: sd = open(device, O_WRONLY);
224: }
225: if (sd < 0) {
226: syslog(LOG_ERR, "cannot found a valid /dev/bpf* entry, do you have bpf in kernel ?");
227: syslog(LOG_ERR, "perhaps you've not created /dev entry on your chroot directory with bpf* entries");
228: return -1;
229: }
230: bzero(&ifr, sizeof(ifr));
231: strncpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name));
232: if (ioctl(sd, BIOCSETIF, (caddr_t)&ifr) < 0) {
233: syslog(LOG_ERR, "interface %s doesn't seem to exist, ioctl: %s\n", strerror(errno), ifr.ifr_name);
234: syslog(LOG_ERR, "you must correct your configuration file with a good option for 'interface ='");
235: return -1;
236: }
237: if (ioctl(sd, BIOCSHDRCMPLT, &yes) < 0) {
238: syslog(LOG_ERR, "cannot do BIOCSHDRCMPLT: %s", strerror(errno));
239: syslog(LOG_ERR, "something is terribly wrong, I can't continue");
240: return -1;
241: }
242:
243: return sd;
244: }
245:
246: int
247: vrrp_network_send_gratuitous_arp(char *if_name, struct ether_addr *ethaddr, struct in_addr addr)
248: {
249: char buffer[ETHER_HDR_LEN + sizeof(struct arp_header)];
250: struct ether_header *ethhdr = (struct ether_header *) buffer;
251: struct arp_header *arph = (struct arp_header *) & buffer[ETHER_HDR_LEN];
252: int sd;
253:
254: memset(ethhdr->ether_dhost, 0xFF, ETHER_ADDR_LEN);
255: bcopy(ethaddr, ethhdr->ether_shost, ETHER_ADDR_LEN);
256: ethhdr->ether_type = htons(ETHERTYPE_ARP);
257: bzero(arph, sizeof(*arph));
258: arph->ar_hrd = htons(ARPHRD_ETHER);
259: arph->ar_pro = htons(ETHERTYPE_IP);
260: arph->ar_hln = ETHER_ADDR_LEN;
261: arph->ar_pln = 4;
262: arph->ar_op = htons(ARPOP_REQUEST);
263: memcpy(arph->ar_sha, ethhdr->ether_shost, ETHER_ADDR_LEN);
264: sd = vrrp_network_open_bpf(if_name);
265: if (sd == -1)
266: return -1;
267: memcpy(arph->ar_spa, &addr, sizeof(struct in_addr));
268: memcpy(arph->ar_tpa, &addr, sizeof(struct in_addr));
269: if (write(sd, buffer, ETHER_HDR_LEN + sizeof(struct arp_header)) == -1) {
270: syslog(LOG_ERR, "cannot write on socket descriptor sd: %s", strerror(errno));
271: close(sd);
272: return -1;
273: }
274: close(sd);
275:
276: return 0;
277: }
278:
279: int
280: vrrp_network_send_gratuitous_arp_ips(struct vrrp_vr * vr, struct ether_addr * ethaddr)
281: {
282: int cpt = 0;
283: struct in_addr addrs[MAX_IP_ALIAS];
284: int size = MAX_IP_ALIAS;
285: char coderet = 0;
286:
287: bzero(addrs, sizeof(addrs));
288: vrrp_misc_get_if_infos(vr->vr_if->if_name, NULL, addrs, &size);
289: while (addrs[cpt].s_addr) {
290: coderet = vrrp_network_send_gratuitous_arp(vr->vr_if->if_name, ethaddr, addrs[cpt]);
291: syslog(LOG_ERR, "send gratuitous arp %s -> %x:%x:%x:%x:%x:%x", inet_ntoa(addrs[cpt]), ethaddr->octet[0], ethaddr->octet[1], ethaddr->octet[2], ethaddr->octet[3], ethaddr->octet[4], ethaddr->octet[5]);
292: cpt++;
293: }
294:
295: return coderet;
296: }
297:
298: #define rtm rtmsg.rthdr
299: char
300: vrrp_network_delete_local_route(struct in_addr addr)
301: {
302: struct routemsg rtmsg;
303: int sd;
304:
305: sd = socket(PF_ROUTE, SOCK_RAW, 0);
306: if (sd == -1) {
307: close(sd);
308: return -1;
309: }
310: bzero(&rtmsg, sizeof(rtmsg));
311: rtm.rtm_type = RTM_DELETE;
312: rtm.rtm_version = RTM_VERSION;
313: #ifdef __FreeBSD__
314: rtm.rtm_flags = RTF_UP | RTF_HOST | RTF_LOCAL;
315: #endif
316: #if __FreeBSD_version < 800059
317: rtm.rtm_flags |= RTF_WASCLONED;
318: #endif
319: #ifdef __NetBSD__
320: rtm.rtm_flags = RTF_UP | RTF_HOST | RTF_CLONED;
321: #endif
322: rtm.rtm_addrs = RTA_DST;
323: rtm.rtm_msglen = sizeof(rtmsg);
324: rtmsg.addr.sin_len = sizeof(rtmsg.addr);
325: rtmsg.addr.sin_family = AF_INET;
326: rtmsg.addr.sin_addr = addr;
327: if (write(sd, &rtmsg, sizeof(rtmsg)) == -1) {
328: close(sd);
329: return -1;
330: }
331: close(sd);
332:
333: return 0;
334: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>