1 /******************************************************************************
2 (c) 2002 Matthew Fredette fredette@netbsd.org
3
4 Some modifications:
5 (c) 2003-2004 Christine Caulfield christine.caulfield@googlemail.com
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16 ******************************************************************************/
17
18 #include <unistd.h>
19 #include <stdio.h>
20 #include <fcntl.h>
21 #include <errno.h>
22 #include <syslog.h>
23 #include <sys/ioctl.h>
24 #include <sys/types.h>
25 #include <sys/time.h>
26 #include <sys/socket.h>
27 #include <sys/uio.h>
28 #include <assert.h>
29
30 #include <net/if.h>
31 #include <net/bpf.h>
32 #ifdef HAVE_NET_IF_ETHER_H
33 #include <net/if_ether.h>
34 #endif /* HAVE_NET_IF_ETHER_H */
35 #ifdef HAVE_NET_ETHERNET_H
36 #include <net/ethernet.h>
37 #endif /* HAVE_NET_ETHERNET_H */
38 #ifdef HAVE_NET_IF_DL_H
39 #include <net/if_dl.h>
40 #endif
41 #include <netinet/in.h>
42
43 #include <cstdlib>
44
45 #include "utils.h"
46 #define _LATD_INTERFACES_IMPL
47 #include "interfaces.h"
48 #include "interfaces-bpf.h"
49
Create()50 LATinterfaces *LATinterfaces::Create()
51 {
52 return new BPFInterfaces();
53 }
54
55 /* this macro helps us size a struct ifreq: */
56 #ifdef HAVE_SOCKADDR_SA_LEN
57 #define SIZEOF_IFREQ(ifr) (sizeof(ifr->ifr_name) + ifr->ifr_addr.sa_len)
58 #else /* !HAVE_SOCKADDR_SA_LEN */
59 #define SIZEOF_IFREQ(ifr) (sizeof(ifr->ifr_name) + sizeof(struct sockaddr))
60 #endif /* !HAVE_SOCKADDR_SA_LEN */
61
62 #define LATD_OFFSETOF(t, m) (((char *) &(((t *) NULL)-> m)) - ((char *) ((t *) NULL)))
63
64 /* the BPF program to capture LAT packets: */
65 static struct bpf_insn lat_bpf_filter[] = {
66
67 /* drop this packet if its ethertype isn't ETHERTYPE_LAT: */
68 BPF_STMT(BPF_LD + BPF_H + BPF_ABS, LATD_OFFSETOF(struct ether_header, ether_type)),
69 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_LAT, 0, 1),
70
71 /* accept this packet: */
72 BPF_STMT(BPF_RET + BPF_K, (u_int) -1),
73
74 /* drop this packet: */
75 BPF_STMT(BPF_RET + BPF_K, 0),
76 };
77
78 /* the BPF program to capture MOP RC packets: */
79 static struct bpf_insn moprc_bpf_filter[] = {
80
81 /* drop this packet if its ethertype isn't ETHERTYPE_MOPRC: */
82 BPF_STMT(BPF_LD + BPF_H + BPF_ABS, LATD_OFFSETOF(struct ether_header, ether_type)),
83 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_MOPRC, 0, 1),
84
85 /* accept this packet: */
86 BPF_STMT(BPF_RET + BPF_K, (u_int) -1),
87
88 /* drop this packet: */
89 BPF_STMT(BPF_RET + BPF_K, 0),
90 };
91
Start(int proto)92 int BPFInterfaces::Start(int proto)
93 {
94 #define DEV_BPF_FORMAT "/dev/bpf%d"
95 char dev_bpf_filename[sizeof(DEV_BPF_FORMAT) + (sizeof(int) * 3) + 1];
96 int minor;
97 int saved_errno;
98 u_int bpf_opt;
99 struct bpf_version version;
100
101 protocol = proto;
102
103 /* loop trying to open a /dev/bpf device: */
104 for(minor = 0;; minor++) {
105
106 /* form the name of the next device to try, then try opening it.
107 if we succeed, we're done: */
108 sprintf(dev_bpf_filename, DEV_BPF_FORMAT, minor);
109 debuglog(("bpf: trying %s\n", dev_bpf_filename));
110 if ((_latd_bpf_fd = open(dev_bpf_filename, O_RDWR)) >= 0) {
111 debuglog(("bpf: opened %s as %d\n", dev_bpf_filename, _latd_bpf_fd));
112 break;
113 }
114
115 /* we failed to open this device. if this device was simply busy,
116 loop: */
117 debuglog(("bpf: failed to open %s: %s\n", dev_bpf_filename, strerror(errno)));
118 if (errno == EBUSY) {
119 continue;
120 }
121
122 /* otherwise, we have failed: */
123 syslog(LOG_ERR, "Can't create LAT protocol socket: %m\n");
124 return -1;
125 }
126
127 /* this macro helps in closing the BPF socket on error: */
128 #define _LATD_RAW_OPEN_ERROR(x) saved_errno = errno; x; errno = saved_errno
129
130 /* check the BPF version: */
131 if (ioctl(_latd_bpf_fd, BIOCVERSION, &version) < 0) {
132 debuglog(("bpf: failed to get the BPF version on %s: %s\n",
133 dev_bpf_filename, strerror(errno)));
134 _LATD_RAW_OPEN_ERROR(close(_latd_bpf_fd));
135 syslog(LOG_ERR, "Can't create LAT protocol socket: %m\n");
136 return -1;
137 }
138 if (version.bv_major != BPF_MAJOR_VERSION
139 || version.bv_minor < BPF_MINOR_VERSION) {
140 debuglog(("bpf: kernel BPF version is %d.%d, my BPF version is %d.%d\n",
141 version.bv_major, version.bv_minor,
142 BPF_MAJOR_VERSION, BPF_MINOR_VERSION));
143 close(_latd_bpf_fd);
144 errno = ENXIO;
145 syslog(LOG_ERR, "Can't create LAT protocol socket: %m\n");
146 return -1;
147 }
148
149 /* put the BPF device into immediate mode: */
150 bpf_opt = true;
151 if (ioctl(_latd_bpf_fd, BIOCIMMEDIATE, &bpf_opt) < 0) {
152 debuglog(("bpf: failed to put %s into immediate mode: %s\n",
153 dev_bpf_filename, strerror(errno)));
154 _LATD_RAW_OPEN_ERROR(close(_latd_bpf_fd));
155 syslog(LOG_ERR, "Can't create LAT protocol socket: %m\n");
156 return -1;
157 }
158 #ifndef __APPLE__
159 /* tell the BPF device we're providing complete Ethernet headers: */
160 bpf_opt = true;
161 if (ioctl(_latd_bpf_fd, BIOCSHDRCMPLT, &bpf_opt) < 0) {
162 debuglog(("bpf: failed to put %s into complete-headers mode: %s\n",
163 dev_bpf_filename, strerror(errno)));
164 _LATD_RAW_OPEN_ERROR(close(_latd_bpf_fd));
165 syslog(LOG_ERR, "Can't create LAT protocol socket: %m\n");
166 return -1;
167 }
168 #endif
169 /* done: */
170 return 0;
171 #undef _LATD_RAW_OPEN_ERROR
172 }
173
174 // Return a list of valid interface numbers and the count
get_all_interfaces(int * ifs,int & num)175 void BPFInterfaces::get_all_interfaces(int *ifs, int &num)
176 {
177 num = 0;
178
179 if (find_interface(NULL) == 0)
180 {
181 ifs[num++] = 0;
182 }
183
184 }
185
186 // Print the name of an interface
ifname(int ifn)187 std::string BPFInterfaces::ifname(int ifn)
188 {
189 std::string str;
190
191 if (ifn == 0 && _latd_bpf_interface_name != NULL) {
192 str.append(_latd_bpf_interface_name);
193 str.append(" ");
194 }
195
196 return str;
197 }
198
199 // Find an interface number by name
find_interface(char * ifname)200 int BPFInterfaces::find_interface(char *ifname)
201 {
202 int saved_errno;
203 int dummy_fd;
204 char ifreq_buffer[16384]; /* FIXME - magic constant. */
205 struct ifconf ifc;
206 struct ifreq *ifr;
207 struct ifreq *ifr_user;
208 size_t ifr_offset;
209 struct sockaddr_in saved_ip_address;
210 short saved_flags;
211 #ifdef HAVE_AF_LINK
212 struct ifreq *link_ifreqs[20]; /* FIXME - magic constant. */
213 size_t link_ifreqs_count;
214 size_t link_ifreqs_i;
215 struct sockaddr_dl *sadl;
216 #endif /* HAVE_AF_LINK */
217
218 /* if we have already chosen an interface, ignore this one: */
219 if (_latd_bpf_interface_name != NULL) {
220 return (-1);
221 }
222
223 /* make a dummy socket so we can read the interface list: */
224 if ((dummy_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
225 return (-1);
226 }
227
228 /* read the interface list: */
229 ifc.ifc_len = sizeof(ifreq_buffer);
230 ifc.ifc_buf = ifreq_buffer;
231 if (ioctl(dummy_fd, SIOCGIFCONF, &ifc) < 0) {
232 saved_errno = errno;
233 close(dummy_fd);
234 errno = saved_errno;
235 return (-1);
236 }
237
238 #ifdef HAVE_AF_LINK
239 /* start our list of link address ifreqs: */
240 link_ifreqs_count = 0;
241 #endif /* HAVE_AF_LINK */
242
243 /* walk the interface list: */
244 ifr_user = NULL;
245 for(ifr_offset = 0;; ifr_offset += SIZEOF_IFREQ(ifr)) {
246
247
248 /* stop walking if we have run out of space in the buffer. note
249 that before we can use SIZEOF_IFREQ, we have to make sure that
250 there is a minimum number of bytes in the buffer to use it
251 (namely, that there's a whole struct sockaddr available): */
252 ifr = (struct ifreq *) (ifreq_buffer + ifr_offset);
253 if ((ifr_offset + sizeof(ifr->ifr_name) + sizeof(struct sockaddr)) > (size_t)ifc.ifc_len
254 || (ifr_offset + SIZEOF_IFREQ(ifr)) > (size_t)ifc.ifc_len) {
255 errno = ENOENT;
256 break;
257 }
258
259 #ifdef HAVE_AF_LINK
260 /* if this is a hardware address, save it: */
261 if (ifr->ifr_addr.sa_family == AF_LINK) {
262 if (link_ifreqs_count < (sizeof(link_ifreqs) / sizeof(link_ifreqs[0]))) {
263 link_ifreqs[link_ifreqs_count++] = ifr;
264 }
265 continue;
266 }
267 #endif /* HAVE_AF_LINK */
268
269 /* ignore this interface if it doesn't do IP: */
270 if (ifr->ifr_addr.sa_family != AF_INET) {
271 continue;
272 }
273
274 /* get the interface flags, preserving the IP address in the
275 struct ifreq across the call: */
276 saved_ip_address = *((struct sockaddr_in *) &ifr->ifr_addr);
277 if (ioctl(dummy_fd, SIOCGIFFLAGS, ifr) < 0) {
278 ifr = NULL;
279 break;
280 }
281 saved_flags = ifr->ifr_flags;
282 *((struct sockaddr_in *) &ifr->ifr_addr) = saved_ip_address;
283
284 /* ignore this interface if it isn't up and running: */
285 if ((saved_flags & (IFF_UP | IFF_RUNNING)) != (IFF_UP | IFF_RUNNING)) {
286 continue;
287 }
288
289 /* if we don't have an interface yet, take this one depending on
290 whether the user asked for an interface by name or not. if he
291 did, and this is it, take this one. if he didn't, and this isn't a
292 loopback interface, take this one: */
293 if (ifr_user == NULL
294 && (ifname != NULL
295 ? !strncmp(ifr->ifr_name, ifname, sizeof(ifr->ifr_name))
296 : !(ifr->ifr_flags & IFF_LOOPBACK))) {
297 ifr_user = ifr;
298 #ifdef __APPLE__
299 if (ifr->ifr_name[0] == 'l' && ifr->ifr_name[1] == 'o')
300 ifr_user = NULL;
301 #endif
302 }
303 }
304
305 /* close the dummy socket: */
306 saved_errno = errno;
307 close(dummy_fd);
308 errno = saved_errno;
309
310 /* if we don't have an interface to return: */
311 if (ifr_user == NULL) {
312 return (-1);
313 }
314
315 #ifdef HAVE_AF_LINK
316
317 /* we must be able to find an AF_LINK ifreq that gives us the
318 interface's Ethernet address. */
319 ifr = NULL;
320 for(link_ifreqs_i = 0; link_ifreqs_i < link_ifreqs_count; link_ifreqs_i++) {
321 if (!strncmp(link_ifreqs[link_ifreqs_i]->ifr_name,
322 ifr_user->ifr_name,
323 sizeof(ifr_user->ifr_name))) {
324 ifr = link_ifreqs[link_ifreqs_i];
325 break;
326 }
327 }
328 if (ifr == NULL) {
329 return (-1);
330 }
331
332 /* copy out the Ethernet address: */
333 sadl = (struct sockaddr_dl *) &ifr->ifr_addr;
334 memcpy(_latd_bpf_interface_addr, LLADDR(sadl), sadl->sdl_alen);
335
336 #else /* !HAVE_AF_LINK */
337 #error "must have AF_LINK for now"
338 #endif /* !HAVE_AF_LINK */
339
340 /* remember this single interface name: */
341 if ((_latd_bpf_interface_name = strdup(ifr_user->ifr_name)) == NULL) {
342 abort();
343 }
344
345 /* this zero is a fake interface index: */
346 debuglog(("bpf: interface Ethernet address is %02x:%02x:%02x:%02x:%02x:%02x\n",
347 _latd_bpf_interface_addr[0],
348 _latd_bpf_interface_addr[1],
349 _latd_bpf_interface_addr[2],
350 _latd_bpf_interface_addr[3],
351 _latd_bpf_interface_addr[4],
352 _latd_bpf_interface_addr[5]));
353 return (0);
354 }
355
356 // true if this class defines one FD for each active
357 // interface, false if one fd is used for all interfaces.
one_fd_per_interface()358 bool BPFInterfaces::one_fd_per_interface()
359 {
360 return false;
361 }
362
363 // Return the FD for this interface (will only be called once for
364 // select if above returns false)
get_fd(int ifn)365 int BPFInterfaces::get_fd(int ifn)
366 {
367 return _latd_bpf_fd;
368 }
369
370 // Send a packet to a given macaddr
send_packet(int ifn,unsigned char macaddr[],unsigned char * data,int len)371 int BPFInterfaces::send_packet(int ifn, unsigned char macaddr[], unsigned char *data, int len)
372 {
373 struct ether_header ether_packet;
374 struct iovec iov[2];
375
376 /* we only support one interface: */
377 assert(ifn == 0);
378
379 /* make the Ethernet header: */
380 memcpy(ether_packet.ether_dhost, macaddr, ETHER_ADDR_LEN);
381 memcpy(ether_packet.ether_shost, _latd_bpf_interface_addr, ETHER_ADDR_LEN);
382 ether_packet.ether_type = htons(protocol);
383
384 /* write this packet: */
385 iov[0].iov_base = (char* )ðer_packet;
386 iov[0].iov_len = sizeof(ether_packet);
387 iov[1].iov_base = (char *)data;
388 iov[1].iov_len = len;
389 if (writev(_latd_bpf_fd, iov, 2) < 0) {
390 syslog(LOG_ERR, "writev: %m");
391 return -1;
392 }
393
394 return 0;
395 }
396
397
398 #define CONT_OR_RET() \
399 if (_latd_bpf_buffer_offset < _latd_bpf_buffer_end) {\
400 continue;\
401 } else {\
402 if (_latd_bpf_buffer_offset_next <= _latd_bpf_buffer_end) \
403 more = true; \
404 return 0; \
405 }
406
407 // Receive a packet from a given interface
recv_packet(int sockfd,int & ifn,unsigned char macaddr[],unsigned char * data,int maxlen,bool & more)408 int BPFInterfaces::recv_packet(int sockfd, int &ifn, unsigned char macaddr[], unsigned char *data, int maxlen, bool &more)
409 {
410 ssize_t buffer_end;
411 struct bpf_hdr the_bpf_header;
412 unsigned int _latd_bpf_buffer_offset_next;
413
414 more = false;
415
416 /* loop until we have something to return: */
417 for(;;) {
418
419 debuglog(("buffer_offset=%d, buffer_end=%d\n", _latd_bpf_buffer_offset,_latd_bpf_buffer_end));
420 /* if the buffer is empty, fill it: */
421 if (_latd_bpf_buffer_offset
422 >= _latd_bpf_buffer_end) {
423
424 // Is there really anything to read? we really don't want to
425 // block here.
426 int bytes;
427 if (ioctl(sockfd, FIONREAD, &bytes) == 0 &&
428 bytes == 0) {
429 return 0;
430 }
431 /* read the BPF socket: */
432 debuglog(("bpf: calling read\n"));
433 buffer_end = read(sockfd,
434 _latd_bpf_buffer,
435 _latd_bpf_buffer_size);
436 if (buffer_end <= 0) {
437 if (errno == EAGAIN) return 0;
438 debuglog(("bpf: failed to read packets: %s\n", strerror(errno)));
439 return (-1);
440 }
441 debuglog(("bpf: read %d bytes of packets\n", buffer_end));
442 _latd_bpf_buffer_offset = 0;
443 _latd_bpf_buffer_end = buffer_end;
444 }
445
446 /* if there's not enough for a BPF header, flush the buffer: */
447 if ((_latd_bpf_buffer_offset
448 + sizeof(the_bpf_header))
449 > _latd_bpf_buffer_end) {
450 debuglog(("bpf: flushed garbage BPF header bytes\n"));
451 _latd_bpf_buffer_end = 0;
452 return 0;
453 }
454
455 /* get the BPF header and check it: */
456 memcpy(&the_bpf_header,
457 _latd_bpf_buffer
458 + _latd_bpf_buffer_offset,
459 sizeof(the_bpf_header));
460 _latd_bpf_buffer_offset_next = _latd_bpf_buffer_offset +
461 BPF_WORDALIGN(the_bpf_header.bh_hdrlen + the_bpf_header.bh_caplen);
462 _latd_bpf_buffer_offset += the_bpf_header.bh_hdrlen;
463
464 /* if we're missing some part of the packet: */
465 if (the_bpf_header.bh_caplen != the_bpf_header.bh_datalen
466 || ((_latd_bpf_buffer_offset + the_bpf_header.bh_datalen)
467 > _latd_bpf_buffer_end)) {
468 debuglog(("bpf: flushed truncated BPF packet (caplen %d, datalen %d, offset %d, end %d\n",
469 the_bpf_header.bh_caplen, the_bpf_header.bh_datalen,
470 _latd_bpf_buffer_offset, _latd_bpf_buffer_end));
471 _latd_bpf_buffer_offset = _latd_bpf_buffer_offset_next;
472 CONT_OR_RET();
473 }
474
475 /* silently ignore packets that don't even have Ethernet headers,
476 and those packets that we transmitted: */
477 if (the_bpf_header.bh_datalen < sizeof(struct ether_header)
478 || !memcmp(((struct ether_header *)
479 (_latd_bpf_buffer
480 + _latd_bpf_buffer_offset))->ether_shost,
481 _latd_bpf_interface_addr,
482 ETHER_ADDR_LEN)) {
483 /* silently ignore packets from us: */
484 if (the_bpf_header.bh_datalen < sizeof(struct ether_header))
485 debuglog(("ignoring short packet of %d bytes\n", the_bpf_header.bh_datalen));
486 else
487 debuglog(("ignoring packet from us\n"));
488 _latd_bpf_buffer_offset = _latd_bpf_buffer_offset_next;
489 CONT_OR_RET();
490 }
491 debuglog(("bpf: packet from %02x:%02x:%02x:%02x:%02x:%02x\n",
492 ((struct ether_header *) (_latd_bpf_buffer + _latd_bpf_buffer_offset))->ether_shost[0],
493 ((struct ether_header *) (_latd_bpf_buffer + _latd_bpf_buffer_offset))->ether_shost[1],
494 ((struct ether_header *) (_latd_bpf_buffer + _latd_bpf_buffer_offset))->ether_shost[2],
495 ((struct ether_header *) (_latd_bpf_buffer + _latd_bpf_buffer_offset))->ether_shost[3],
496 ((struct ether_header *) (_latd_bpf_buffer + _latd_bpf_buffer_offset))->ether_shost[4],
497 ((struct ether_header *) (_latd_bpf_buffer + _latd_bpf_buffer_offset))->ether_shost[5]));
498
499 /* if the caller hasn't provided a large enough buffer: */
500 if (maxlen < 0 || (unsigned int)maxlen < the_bpf_header.bh_datalen) {
501 errno = EIO;
502 _latd_bpf_buffer_offset = _latd_bpf_buffer_offset_next;
503 return (-1);
504 }
505
506 /* return this captured packet to the user. the caller doesn't
507 want the Ethernet header as part of the packet, but he does
508 want the source address. */
509 memcpy(data,
510 _latd_bpf_buffer
511 + _latd_bpf_buffer_offset
512 + sizeof(struct ether_header),
513 the_bpf_header.bh_datalen
514 - sizeof(struct ether_header));
515 ifn = 0;
516 memcpy(macaddr,
517 ((struct ether_header *) (_latd_bpf_buffer
518 + _latd_bpf_buffer_offset))->ether_shost,
519 ETHER_ADDR_LEN);
520 _latd_bpf_buffer_offset = _latd_bpf_buffer_offset_next;
521 if (_latd_bpf_buffer_offset < _latd_bpf_buffer_end)
522 more = true;
523 return (the_bpf_header.bh_datalen
524 - sizeof(struct ether_header));
525 }
526 /* NOTREACHED */
527 }
528
529 /* This is the LAT multicast address */
store_lat_multicast(unsigned char * addr)530 static void store_lat_multicast(unsigned char *addr)
531 {
532 addr[0] = 0x09;
533 addr[1] = 0x00;
534 addr[2] = 0x2b;
535 addr[3] = 0x00;
536 addr[4] = 0x00;
537 addr[5] = 0x0f;
538 }
539
540
541 // Open a connection on an interface
set_lat_multicast(int ifn)542 int BPFInterfaces::set_lat_multicast(int ifn)
543 {
544 struct ifreq interface_ifreq;
545 struct bpf_program program;
546 int dummy_fd;
547 #ifdef HAVE_AF_LINK
548 struct sockaddr_dl *sockdl;
549 #endif
550
551 memset(&interface_ifreq, 0, sizeof(interface_ifreq));
552
553 /* if we don't have an interface, bail: */
554 if (ifn != 0 || _latd_bpf_interface_name == NULL) {
555 syslog(LOG_ERR, "No interfaces\n");
556 return -1;
557 }
558 strcpy(interface_ifreq.ifr_name, _latd_bpf_interface_name);
559
560 /* point the BPF device at the interface we're using: */
561 if (ioctl(_latd_bpf_fd, BIOCSETIF, &interface_ifreq) < 0) {
562 debuglog(("bpf: failed to point BPF socket at %s: %s\n",
563 interface_ifreq.ifr_name, strerror(errno)));
564 syslog(LOG_ERR, "Can't create LAT protocol socket: %m\n");
565 return -1;
566 }
567
568 /* set the filter on the BPF device: */
569 program.bf_len = sizeof(lat_bpf_filter) / sizeof(lat_bpf_filter[0]);
570 program.bf_insns = lat_bpf_filter;
571 if (ioctl(_latd_bpf_fd, BIOCSETF, &program) < 0) {
572 debuglog(("bpf: failed to set the filter: %s\n", strerror(errno)));
573 syslog(LOG_ERR, "Can't create LAT protocol socket: %m\n");
574 return -1;
575 }
576
577 /* get the BPF read buffer size: */
578 if (ioctl(_latd_bpf_fd, BIOCGBLEN, &_latd_bpf_buffer_size) < 0) {
579 debuglog(("bpf: failed to read the buffer size: %s\n", strerror(errno)));
580 syslog(LOG_ERR, "Can't create LAT protocol socket: %m\n");
581 return -1;
582 }
583 debuglog(("bpf: buffer size is %u\n", _latd_bpf_buffer_size));
584
585 /* allocate the buffer for BPF reads: */
586 if ((_latd_bpf_buffer = (unsigned char *) malloc(_latd_bpf_buffer_size)) == NULL) {
587 abort();
588 }
589 _latd_bpf_buffer_end = _latd_bpf_buffer_offset = 0;
590
591 // Add Multicast membership for LAT on socket
592
593 /* make a dummy socket so we can manipulate an interface: */
594 if ((dummy_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
595 syslog(LOG_ERR, "Can't create a dummy socket: %m\n");
596 return -1;
597 }
598
599 #ifdef HAVE_AF_LINK
600 sockdl = (sockaddr_dl *)&interface_ifreq.ifr_addr;
601 sockdl->sdl_family = AF_LINK;
602 sockdl->sdl_alen = 6;
603 store_lat_multicast((unsigned char *)sockdl->sdl_data);
604 #else
605 interface_ifreq.ifr_addr.sa_family = AF_UNSPEC;
606 store_lat_multicast((unsigned char *)interface_ifreq.ifr_addr.sa_data);
607 #endif
608 #ifdef HAVE_SOCKADDR_SA_LEN
609 interface_ifreq.ifr_addr.sa_len = sizeof(interface_ifreq.ifr_addr);
610 #endif /* HAVE_SOCKADDR_SA_LEN */
611
612
613 if (ioctl(dummy_fd, SIOCADDMULTI, &interface_ifreq) < 0) {
614 debuglog(("bpf: failed to add to the multicast list for interface for %s: %s\n",
615 interface_ifreq.ifr_name, strerror(errno)));
616 syslog(LOG_ERR, "Can't create LAT protocol socket: %m\n");
617 close(dummy_fd);
618 return -1;
619 }
620
621 /* close the dummy socket: */
622 close(dummy_fd);
623
624 return 0;
625 }
626
627 // Close an interface.
remove_lat_multicast(int ifn)628 int BPFInterfaces::remove_lat_multicast(int ifn)
629 {
630 struct ifreq interface_ifreq;
631 int dummy_fd;
632 #ifdef HAVE_AF_LINK
633 struct sockaddr_dl *sockdl;
634 #endif
635
636 memset(&interface_ifreq, 0, sizeof(interface_ifreq));
637
638 /* if we don't have an interface, bail: */
639 if (ifn != 0 || _latd_bpf_interface_name == NULL) {
640 syslog(LOG_ERR, "No interfaces\n");
641 return -1;
642 }
643 strcpy(interface_ifreq.ifr_name, _latd_bpf_interface_name);
644
645 // Delete Multicast membership for LAT on socket
646
647 /* make a dummy socket so we can manipulate an interface: */
648 if ((dummy_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
649 syslog(LOG_ERR, "Can't create a dummy socket: %m\n");
650 return -1;
651 }
652
653 #ifdef HAVE_AF_LINK
654 sockdl = (sockaddr_dl *)&interface_ifreq.ifr_addr;
655 sockdl->sdl_family = AF_LINK;
656 sockdl->sdl_alen = 6;
657 store_lat_multicast((unsigned char *)sockdl->sdl_data);
658 #else
659 interface_ifreq.ifr_addr.sa_family = AF_UNSPEC;
660 store_lat_multicast((unsigned char *)interface_ifreq.ifr_addr.sa_data);
661 #endif
662 #ifdef HAVE_SOCKADDR_SA_LEN
663 interface_ifreq.ifr_addr.sa_len = sizeof(interface_ifreq.ifr_addr);
664 #endif /* HAVE_SOCKADDR_SA_LEN */
665
666 if (ioctl(dummy_fd, SIOCDELMULTI, &interface_ifreq) < 0) {
667 debuglog(("bpf: failed to delete from the multicast list for interface for %s: %s\n",
668 interface_ifreq.ifr_name, strerror(errno)));
669 syslog(LOG_ERR, "can't remove socket multicast: %m\n");
670 close(dummy_fd);
671 return -1;
672 }
673
674 /* close the dummy socket: */
675 close(dummy_fd);
676
677 return 0;
678 }
679
bind_socket(int ifn)680 int BPFInterfaces::bind_socket(int ifn)
681 {
682 struct ifreq interface_ifreq;
683 struct bpf_program program;
684
685 /* if we don't have an interface, bail: */
686 if (ifn != 0 || _latd_bpf_interface_name == NULL) {
687 syslog(LOG_ERR, "No interfaces\n");
688 return -1;
689 }
690 strcpy(interface_ifreq.ifr_name, _latd_bpf_interface_name);
691
692 /* point the BPF device at the interface we're using: */
693 if (ioctl(_latd_bpf_fd, BIOCSETIF, &interface_ifreq) < 0) {
694 debuglog(("bpf: failed to point BPF socket at %s: %s\n",
695 interface_ifreq.ifr_name, strerror(errno)));
696 syslog(LOG_ERR, "Can't create LAT protocol socket: %m\n");
697 return -1;
698 }
699
700 /* set the filter on the BPF device: */
701 program.bf_len = sizeof(moprc_bpf_filter) / sizeof(moprc_bpf_filter[0]);
702 program.bf_insns = moprc_bpf_filter;
703 if (ioctl(_latd_bpf_fd, BIOCSETF, &program) < 0) {
704 debuglog(("bpf: failed to set the filter: %s\n", strerror(errno)));
705 syslog(LOG_ERR, "Can't create LAT protocol socket: %m\n");
706 return -1;
707 }
708
709 /* get the BPF read buffer size: */
710 if (ioctl(_latd_bpf_fd, BIOCGBLEN, &_latd_bpf_buffer_size) < 0) {
711 debuglog(("bpf: failed to read the buffer size: %s\n", strerror(errno)));
712 syslog(LOG_ERR, "Can't create LAT protocol socket: %m\n");
713 return -1;
714 }
715 debuglog(("bpf: buffer size is %u\n", _latd_bpf_buffer_size));
716
717 /* allocate the buffer for BPF reads: */
718 if ((_latd_bpf_buffer = (unsigned char *) malloc(_latd_bpf_buffer_size)) == NULL) {
719 abort();
720 }
721 _latd_bpf_buffer_end = _latd_bpf_buffer_offset = 0;
722 return 0;
723 }
724
725 int LATinterfaces::ProtoLAT = ETHERTYPE_LAT;
726 int LATinterfaces::ProtoMOP = ETHERTYPE_MOPRC;
727