1 /*
2  * net library functions.
3  * Copyright (C) 2003, 2004, 2005, 2006 Mondru AB.
4  * Copyright (c) 2006-2008 David Bird <david@coova.com>
5  *
6  * The contents of this file may be used under the terms of the GNU
7  * General Public License Version 2, provided that the above copyright
8  * notice and this permission notice is included in all copies or
9  * substantial portions of the software.
10  *
11  */
12 
13 #include "system.h"
14 #include "syserr.h"
15 #include "options.h"
16 #include "net.h"
17 
dev_set_flags(char const * dev,int flags)18 int dev_set_flags(char const *dev, int flags) {
19   struct ifreq ifr;
20   int fd;
21 
22   memset(&ifr, 0, sizeof(ifr));
23   ifr.ifr_flags = flags;
24   strncpy(ifr.ifr_name, dev, IFNAMSIZ);
25   ifr.ifr_name[IFNAMSIZ-1] = 0; /* Make sure to terminate */
26 
27   if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
28     log_err(errno,"socket() failed");
29     return -1;
30   }
31 
32   if (ioctl(fd, SIOCSIFFLAGS, &ifr)) {
33     log_err(errno,"ioctl(SIOCSIFFLAGS) failed");
34     close(fd);
35     return -1;
36   }
37 
38   close(fd);
39 
40   return 0;
41 }
42 
dev_get_flags(char const * dev,int * flags)43 int dev_get_flags(char const *dev, int *flags) {
44   struct ifreq ifr;
45   int fd;
46 
47   memset(&ifr, 0, sizeof(ifr));
48   strncpy(ifr.ifr_name, dev, IFNAMSIZ);
49   ifr.ifr_name[IFNAMSIZ-1] = 0;
50 
51   if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
52     log_err(errno, "socket() failed");
53     return -1;
54   }
55 
56   if (ioctl(fd, SIOCGIFFLAGS, &ifr)) {
57     log_err(errno, "ioctl(SIOCSIFFLAGS) failed");
58     close(fd);
59     return -1;
60   }
61 
62   close(fd);
63 
64   *flags = ifr.ifr_flags;
65 
66   return 0;
67 }
68 
dev_set_address(char const * devname,struct in_addr * address,struct in_addr * dstaddr,struct in_addr * netmask)69 int dev_set_address(char const *devname, struct in_addr *address,
70 		    struct in_addr *dstaddr, struct in_addr *netmask) {
71   struct ifreq ifr;
72   int fd;
73 
74   memset (&ifr, 0, sizeof (ifr));
75   ifr.ifr_addr.sa_family = AF_INET;
76   ifr.ifr_dstaddr.sa_family = AF_INET;
77 
78 #if defined(__linux__)
79   ifr.ifr_netmask.sa_family = AF_INET;
80 
81 #elif defined(__FreeBSD__) || defined (__APPLE__) || defined (__OpenBSD__) || defined (__NetBSD__)
82   ((struct sockaddr_in *) &ifr.ifr_addr)->sin_len = sizeof (struct sockaddr_in);
83   ((struct sockaddr_in *) &ifr.ifr_dstaddr)->sin_len = sizeof (struct sockaddr_in);
84 #endif
85 
86   strncpy(ifr.ifr_name, devname, IFNAMSIZ);
87   ifr.ifr_name[IFNAMSIZ-1] = 0; /* Make sure to terminate */
88 
89   /* Create a channel to the NET kernel. */
90   if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
91     log_err(errno, "socket() failed");
92     return -1;
93   }
94 
95   if (address) { /* Set the interface address */
96     ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = address->s_addr;
97     if (ioctl(fd, SIOCSIFADDR, (void *) &ifr) < 0) {
98       if (errno != EEXIST) {
99 	log_err(errno, "ioctl(SIOCSIFADDR) failed");
100       }
101       else {
102 	log_warn(errno, "ioctl(SIOCSIFADDR): Address already exists");
103       }
104       close(fd);
105       return -1;
106     }
107   }
108 
109   if (dstaddr) { /* Set the destination address */
110     ((struct sockaddr_in *) &ifr.ifr_dstaddr)->sin_addr.s_addr = dstaddr->s_addr;
111     if (ioctl(fd, SIOCSIFDSTADDR, (caddr_t) &ifr) < 0) {
112       log_err(errno, "ioctl(SIOCSIFDSTADDR) failed");
113       close(fd);
114       return -1;
115     }
116   }
117 
118   if (netmask) { /* Set the netmask */
119 #if defined(__linux__)
120     ((struct sockaddr_in *) &ifr.ifr_netmask)->sin_addr.s_addr =  netmask->s_addr;
121 
122 #elif defined(__FreeBSD__) || defined (__APPLE__) || defined (__OpenBSD__) || defined (__NetBSD__)
123     ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr =  netmask->s_addr;
124 
125 #elif defined(__sun__)
126     ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr =  netmask->s_addr;
127 #else
128 #error  "Unknown platform!"
129 #endif
130 
131     if (ioctl(fd, SIOCSIFNETMASK, (void *) &ifr) < 0) {
132       log_err(errno, "ioctl(SIOCSIFNETMASK) failed");
133       close(fd);
134       return -1;
135     }
136   }
137 
138   close(fd);
139 
140   return dev_set_flags(devname, IFF_UP | IFF_RUNNING);
141 }
142 
net_init(net_interface * netif,char * ifname,uint16_t protocol,int promisc,uint8_t * mac)143 int net_init(net_interface *netif, char *ifname, uint16_t protocol, int promisc, uint8_t *mac) {
144   memset(netif, 0, sizeof(net_interface));
145   strncpy(netif->devname, ifname, IFNAMSIZ);
146   netif->devname[IFNAMSIZ] = 0;
147   netif->protocol = protocol;
148 
149   if (promisc) netif->flags |= NET_PROMISC;
150 
151   if (mac) {
152     netif->flags |= NET_USEMAC;
153     memcpy(netif->hwaddr, mac, PKT_ETH_ALEN);
154   }
155 
156   return net_open(netif);
157 }
158 
net_open(net_interface * netif)159 int net_open(net_interface *netif) {
160   net_close(netif);
161   net_gflags(netif);
162 
163   if (!(netif->devflags & IFF_UP) || !(netif->devflags & IFF_RUNNING)) {
164     struct in_addr noaddr;
165     net_sflags(netif, netif->devflags | IFF_NOARP);
166     memset(&noaddr, 0, sizeof(noaddr));
167     dev_set_address(netif->devname, &noaddr, NULL, NULL);
168   }
169 
170   return net_open_eth(netif);
171 }
172 
net_reopen(net_interface * netif)173 int net_reopen(net_interface *netif) {
174   net_close(netif);
175   return net_open(netif);
176 }
177 
net_set_address(net_interface * netif,struct in_addr * address,struct in_addr * dstaddr,struct in_addr * netmask)178 int net_set_address(net_interface *netif, struct in_addr *address,
179 		    struct in_addr *dstaddr, struct in_addr *netmask) {
180   netif->address.s_addr = address->s_addr;
181   netif->gateway.s_addr = dstaddr->s_addr;
182   netif->netmask.s_addr = netmask->s_addr;
183 
184   return dev_set_address(netif->devname, address, dstaddr, netmask);
185 }
186 
net_read(net_interface * netif,void * d,size_t dlen)187 ssize_t net_read(net_interface *netif, void *d, size_t dlen) {
188   ssize_t len;
189 
190   if ((len = read(netif->fd, d, dlen)) < 0) {
191 #ifdef ENETDOWN
192     if (errno == ENETDOWN) {
193       net_reopen(netif);
194     }
195 #endif
196     log_err(errno, "read(fd=%d, len=%d) == %d", netif->fd, dlen, len);
197     return -1;
198   }
199 
200   return len;
201 }
202 
net_write(net_interface * netif,void * d,size_t dlen)203 ssize_t net_write(net_interface *netif, void *d, size_t dlen) {
204   ssize_t len;
205 
206   if ((len = write(netif->fd, d, dlen)) < 0) {
207 #ifdef ENETDOWN
208     if (errno == ENETDOWN) {
209       net_reopen(netif);
210     }
211 #endif
212     log_err(errno, "write(fd=%d, len=%d) failed", netif->fd, dlen);
213     return -1;
214   }
215 
216   return len;
217 }
218 
net_route(struct in_addr * dst,struct in_addr * gateway,struct in_addr * mask,int delete)219 int net_route(struct in_addr *dst, struct in_addr *gateway, struct in_addr *mask, int delete) {
220 
221   /* TODO: solaris!  */
222 
223 #if defined(__linux__)
224   struct rtentry r;
225   int fd;
226 
227   memset (&r, 0, sizeof (r));
228   r.rt_flags = RTF_UP | RTF_GATEWAY; /* RTF_HOST not set */
229 
230   /* Create a channel to the NET kernel. */
231   if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
232     log_err(errno, "socket() failed");
233     return -1;
234   }
235 
236   r.rt_dst.sa_family     = AF_INET;
237   r.rt_gateway.sa_family = AF_INET;
238   r.rt_genmask.sa_family = AF_INET;
239   ((struct sockaddr_in *) &r.rt_dst)->sin_addr.s_addr = dst->s_addr;
240   ((struct sockaddr_in *) &r.rt_gateway)->sin_addr.s_addr = gateway->s_addr;
241   ((struct sockaddr_in *) &r.rt_genmask)->sin_addr.s_addr = mask->s_addr;
242 
243   if (delete) {
244     if (ioctl(fd, SIOCDELRT, (void *) &r) < 0) {
245       log_err(errno,"ioctl(SIOCDELRT) failed");
246       close(fd);
247       return -1;
248     }
249   }
250   else {
251     if (ioctl(fd, SIOCADDRT, (void *) &r) < 0) {
252       log_err(errno, "ioctl(SIOCADDRT) failed");
253       close(fd);
254       return -1;
255     }
256   }
257   close(fd);
258   return 0;
259 
260 #elif defined(__FreeBSD__) || defined (__APPLE__) || defined (__OpenBSD__) || defined (__NetBSD__)
261 
262   struct {
263     struct rt_msghdr rt;
264     struct sockaddr_in dst;
265     struct sockaddr_in gate;
266     struct sockaddr_in mask;
267   } req;
268 
269   int fd;
270   struct rt_msghdr *rtm;
271 
272   if ((fd = socket(AF_ROUTE, SOCK_RAW, 0)) == -1) {
273     log_err(errno, "socket() failed");
274     return -1;
275   }
276 
277   memset(&req, 0, sizeof(req));
278 
279   rtm  = &req.rt;
280 
281   rtm->rtm_msglen = sizeof(req);
282   rtm->rtm_version = RTM_VERSION;
283   if (delete) {
284     rtm->rtm_type = RTM_DELETE;
285   }
286   else {
287     rtm->rtm_type = RTM_ADD;
288   }
289   rtm->rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC;  /* TODO */
290   rtm->rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
291   rtm->rtm_pid = getpid();
292   rtm->rtm_seq = 0044;                                 /* TODO */
293 
294   req.dst.sin_family       = AF_INET;
295   req.dst.sin_len          = sizeof(req.dst);
296   req.mask.sin_family      = AF_INET;
297   req.mask.sin_len         = sizeof(req.mask);
298   req.gate.sin_family      = AF_INET;
299   req.gate.sin_len         = sizeof(req.gate);
300 
301   req.dst.sin_addr.s_addr  = dst->s_addr;
302   req.mask.sin_addr.s_addr = mask->s_addr;
303   req.gate.sin_addr.s_addr = gateway->s_addr;
304 
305   if (write(fd, rtm, rtm->rtm_msglen) < 0) {
306     log_err(errno, "write() failed");
307     close(fd);
308     return -1;
309   }
310   close(fd);
311   return 0;
312 
313 #elif defined(__sun__)
314   log_err(errno, "Could not set up routing on Solaris. Please add route manually.");
315   return 0;
316 #else
317 #error  "Unknown platform!"
318 #endif
319 }
320 
321 #if defined(__linux__)
322 
323 /**
324  * Opens an Ethernet interface. As an option the interface can be set in
325  * promisc mode. If not null macaddr and ifindex are filled with the
326  * interface mac address and index
327  **/
net_open_eth(net_interface * netif)328 int net_open_eth(net_interface *netif) {
329   struct ifreq ifr;
330   struct packet_mreq mr;
331   struct sockaddr_ll sa;
332   int option = 1;
333 
334   memset(&ifr, 0, sizeof(ifr));
335 
336   /* Create socket */
337   if ((netif->fd = socket(PF_PACKET, SOCK_RAW, htons(netif->protocol))) < 0) {
338     if (errno == EPERM) {
339       log_err(errno, "Cannot create raw socket. Must be root.");
340     }
341 
342     log_err(errno, "socket(domain=%d, type=%lx, protocol=%d) failed",
343 	    PF_PACKET, SOCK_RAW, netif->protocol);
344 
345     return -1;
346   }
347 
348   /* Enable reception and transmission of broadcast frames */
349   if (setsockopt(netif->fd, SOL_SOCKET, SO_BROADCAST, &option, sizeof(option)) < 0) {
350     log_err(errno, "setsockopt(s=%d, level=%d, optname=%d, optlen=%d) failed",
351 	    netif->fd, SOL_SOCKET, SO_BROADCAST, sizeof(option));
352     return -1;
353   }
354 
355   /* Get the MAC address of our interface */
356   strncpy(ifr.ifr_name, netif->devname, sizeof(ifr.ifr_name));
357   if (ioctl(netif->fd, SIOCGIFHWADDR, &ifr) < 0) {
358     log_err(errno, "ioctl(d=%d, request=%d) failed", netif->fd, SIOCGIFHWADDR);
359     return -1;
360   }
361 
362   if (ifr.ifr_hwaddr.sa_family == ARPHRD_ETHER) {
363 
364     netif->flags |= NET_ETHHDR;
365 
366     if ((netif->flags & NET_USEMAC) == 0)
367       memcpy(netif->hwaddr, ifr.ifr_hwaddr.sa_data, PKT_ETH_ALEN);
368   }
369 
370   if (netif->hwaddr[0] & 0x01) {
371     log_err(0, "Ethernet has broadcast or multicast address: %.16s", netif->devname);
372   }
373 
374   /* Get the current interface address, network, and any destination address */
375 
376   /* Verify that MTU = ETH_DATA_LEN */
377   strncpy(ifr.ifr_name, netif->devname, sizeof(ifr.ifr_name));
378   if (ioctl(netif->fd, SIOCGIFMTU, &ifr) < 0) {
379     log_err(errno, "ioctl(d=%d, request=%d) failed", netif->fd, SIOCGIFMTU);
380     return -1;
381   }
382   if (ifr.ifr_mtu != ETH_DATA_LEN) {
383     log_err(0, "MTU does not match EHT_DATA_LEN: %d %d", ifr.ifr_mtu, ETH_DATA_LEN);
384     return -1;
385   }
386 
387   /* Get ifindex */
388   strncpy(ifr.ifr_name, netif->devname, sizeof(ifr.ifr_name));
389   if (ioctl(netif->fd, SIOCGIFINDEX, &ifr) < 0) {
390     log_err(errno, "ioctl(SIOCFIGINDEX) failed");
391   }
392   netif->ifindex = ifr.ifr_ifindex;
393 
394   /* Set interface in promisc mode */
395   if (netif->flags & NET_PROMISC) {
396     memset(&mr,0,sizeof(mr));
397     mr.mr_ifindex = ifr.ifr_ifindex;
398     mr.mr_type =  PACKET_MR_PROMISC;
399     if (setsockopt(netif->fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, (char *)&mr, sizeof(mr)) < 0) {
400       log_err(errno, "setsockopt(s=%d, level=%d, optname=%d, optlen=%d) failed",
401 	      netif->fd, SOL_SOCKET, PACKET_ADD_MEMBERSHIP, sizeof(mr));
402       return -1;
403     }
404   }
405 
406   /* Bind to particular interface */
407   memset(&sa, 0, sizeof(sa));
408   sa.sll_family = AF_PACKET;
409   sa.sll_protocol = htons(netif->protocol);
410   sa.sll_ifindex = ifr.ifr_ifindex;
411 
412   if (bind(netif->fd, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
413     log_err(errno, "bind(sockfd=%d) failed", netif->fd);
414     return -1;
415   }
416 
417   return 0;
418 }
419 
420 #elif defined (__FreeBSD__) || defined (__APPLE__) || defined (__OpenBSD__) || defined (__NetBSD__)
421 
net_getmac(const char * ifname,char * macaddr)422 int net_getmac(const char *ifname, char *macaddr) {
423 
424   struct ifaddrs *ifap, *ifa;
425   struct sockaddr_dl *sdl;
426 
427   if (getifaddrs(&ifap)) {
428     log_err(errno, "getifaddrs() failed!");
429     return -1;
430   }
431 
432   ifa = ifap;
433   while (ifa) {
434     if ((strcmp(ifa->ifa_name, ifname) == 0) &&
435 	(ifa->ifa_addr->sa_family == AF_LINK)) {
436       sdl = (struct sockaddr_dl *)ifa->ifa_addr;
437       switch(sdl->sdl_type) {
438       case IFT_ETHER:
439 #ifdef IFT_IEEE80211
440       case IFT_IEEE80211:
441 #endif
442 	break;
443       default:
444 	continue;
445       }
446       if (sdl->sdl_alen != PKT_ETH_ALEN) {
447 	log_err(errno, "Wrong sdl_alen!");
448 	freeifaddrs(ifap);
449 	return -1;
450       }
451       memcpy(macaddr, LLADDR(sdl), PKT_ETH_ALEN);
452       freeifaddrs(ifap);
453       return 0;
454     }
455     ifa = ifa->ifa_next;
456   }
457   freeifaddrs(ifap);
458   return -1;
459 }
460 
461 /**
462  * Opens an Ethernet interface. As an option the interface can be set in
463  * promisc mode. If not null macaddr and ifindex are filled with the
464  * interface mac address and index
465  **/
466 
467 /* Relevant IOCTLs
468 FIONREAD Get the number of bytes in input buffer
469 SIOCGIFADDR Get interface address (IP)
470 BIOCGBLEN, BIOCSBLEN Get and set required buffer length
471 BIOCGDLT Type of underlying data interface
472 BIOCPROMISC Set in promisc mode
473 BIOCFLUSH Flushes the buffer of incoming packets
474 BIOCGETIF, BIOCSETIF Set hardware interface. Uses ift_name
475 BIOCSRTIMEOUT, BIOCGRTIMEOUT Set and get timeout for reads
476 BIOCGSTATS Return stats for the interface
477 BIOCIMMEDIATE Return immediately from reads as soon as packet arrives.
478 BIOCSETF Set filter
479 BIOCVERSION Return the version of BPF
480 BIOCSHDRCMPLT BIOCGHDRCMPLT Set flag of wheather to fill in MAC address
481 BIOCSSEESENT BIOCGSEESENT Return locally generated packets */
482 
net_open_eth(net_interface * netif)483 int net_open_eth(net_interface *netif) {
484   char devname[IFNAMSIZ+5]; /* "/dev/" + ifname */
485   int devnum;
486   struct ifreq ifr;
487   struct ifaliasreq areq;
488   int local_fd;
489   struct bpf_version bv;
490 
491   u_int32_t ipaddr;
492   struct sockaddr_dl hwaddr;
493   unsigned int value;
494 
495   /* Find suitable device */
496   for (devnum = 0; devnum < 255; devnum++) { /* TODO 255 */
497     snprintf(devname, sizeof(devname), "/dev/bpf%d", devnum);
498     devname[sizeof(devname)] = 0;
499     if ((netif->fd = open(devname, O_RDWR)) >= 0) break;
500     if (errno != EBUSY) break;
501   }
502   if (netif->fd < 0) {
503     log_err(errno, "Can't find bpf device");
504     return -1;
505   }
506 
507   /* Set the interface */
508   memset(&ifr, 0, sizeof(ifr));
509   strncpy(ifr.ifr_name, netif->devname, sizeof(ifr.ifr_name));
510   if (ioctl(netif->fd, BIOCSETIF, &ifr) < 0) {
511     log_err(errno,"ioctl() failed");
512     return -1;
513   }
514 
515   /* Get and validate BPF version */
516   if (ioctl(netif->fd, BIOCVERSION, &bv) < 0) {
517     log_err(errno,"ioctl() failed!");
518     return -1;
519   }
520   if (bv.bv_major != BPF_MAJOR_VERSION ||
521       bv.bv_minor < BPF_MINOR_VERSION) {
522     log_err(errno,"wrong BPF version!");
523     return -1;
524   }
525 
526   /* Get the MAC address of our interface */
527   if (net_getmac(netif->devname, netif->hwaddr)) {
528     log_err(0,"Did not find MAC address!");
529   }
530   else {
531     netif->flags |= NET_ETHHDR;
532   }
533 
534   if (netif->hwaddr[0] & 0x01) {
535     log_err(0, "Ethernet has broadcast or multicast address: %.16s", netif->devname);
536     return -1;
537   }
538 
539   /* Set interface in promisc mode */
540   if (netif->flags & NET_PROMISC) {
541     value = 1;
542     if (ioctl(netif->fd, BIOCPROMISC, NULL) < 0) {
543       log_err(errno,"ioctl() failed!");
544       return -1;
545     }
546     value = 1;
547     if (ioctl(netif->fd, BIOCSHDRCMPLT, &value) < 0) {
548       log_err(errno,"ioctl() failed!");
549       return -1;
550     }
551   }
552   else {
553     value = 0;
554     if (ioctl(netif->fd, BIOCSHDRCMPLT, &value) < 0) {
555       log_err(errno,"ioctl() failed!");
556       return -1;
557     }
558   }
559 
560   /* Make sure reads return as soon as packet has been received */
561   value = 1;
562   if (ioctl(netif->fd, BIOCIMMEDIATE, &value) < 0) {
563     log_err(errno,"ioctl() failed!");
564     return -1;
565   }
566 
567   return 0;
568 }
569 
570 #endif
571 
572