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* )&ether_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