8 #include "wvinterface.h"
12 #include "wvsubproc.h"
15 #include <sys/ioctl.h>
16 #include <sys/socket.h>
18 #include <net/if_arp.h>
19 #include <net/route.h>
22 #include <linux/sockios.h>
25 #include <linux/wireless.h>
28 const typeof(x) _x = (x); \
29 const typeof(y) _y = (y); \
30 (void) (&_x == &_y); \
33 WvInterfaceDictBase WvInterfaceDict::slist(15);
34 int WvInterfaceDict::links = 0;
37 WvInterface::WvInterface(WvStringParm _name) :
38 err(
"Net Interface",
WvLog::Error), name(_name)
40 my_hwaddr = my_ipaddr = NULL;
45 WvInterface::~WvInterface()
55 sock = socket(AF_INET, SOCK_STREAM, 0);
56 strncpy(ifr->ifr_name, name, IFNAMSIZ-1);
57 ifr->ifr_name[IFNAMSIZ-1] = 0;
59 retval = ioctl(sock, ioctl_num, ifr);
71 sock = socket(AF_INET, SOCK_STREAM, 0);
72 strncpy(ifr->ifr_name, name, IFNAMSIZ-1);
73 ifr->ifr_name[IFNAMSIZ-1] = 0;
75 retval = ioctl(sock, ioctl_num, ifr);
107 if (
req(SIOCGIFHWADDR, &ifr))
108 my_hwaddr =
new WvStringAddr(
"Unknown", WvEncap::Unknown);
110 my_hwaddr = WvAddr::gen(&ifr.ifr_hwaddr);
119 struct ifreq ifr, ifr2;
123 ifr.ifr_addr.sa_family = AF_INET;
124 ifr2.ifr_netmask.sa_family = AF_INET;
125 if (
req(SIOCGIFADDR, &ifr) ||
req(SIOCGIFNETMASK, &ifr2))
128 my_ipaddr =
new WvIPNet(&ifr.ifr_addr, &ifr2.ifr_netmask);
139 ifr.ifr_dstaddr.sa_family = AF_INET;
140 if (!(
getflags() & IFF_POINTOPOINT) ||
req(SIOCGIFDSTADDR, &ifr))
150 int retval =
req(SIOCGIFFLAGS, &ifr);
153 return retval? 0: ifr.ifr_flags;
161 int retval =
req(SIOCGIFFLAGS, &ifr);
164 int newflags = (ifr.ifr_flags & ~clear) | set;
165 if (newflags != ifr.ifr_flags)
167 ifr.ifr_flags = newflags;
168 retval =
req(SIOCSIFFLAGS, &ifr);
169 if (retval && retval != EACCES && retval != EPERM)
176 void WvInterface::up(
bool enable)
178 setflags(IFF_UP, enable ? IFF_UP : 0);
185 return (valid && (
getflags() & IFF_UP)) ? 1 : 0;
189 void WvInterface::promisc(
bool enable)
191 setflags(IFF_PROMISC, enable ? IFF_PROMISC : 0);
198 sockaddr *saddr = addr.sockaddr();
199 memcpy(&ifr.ifr_dstaddr, saddr, addr.sockaddr_len());
201 int retval =
req(SIOCSIFDSTADDR, &ifr);
202 if (retval && retval != EACCES && retval != EPERM)
208 return setflags(IFF_POINTOPOINT, enable ? IFF_POINTOPOINT : 0);
214 return (
getflags() & IFF_PROMISC) ? 1 : 0;
227 err(WvLog::Info,
"Changing %s address to %s (%s bits)\n", name,
230 sock = socket(AF_INET, SOCK_STREAM, 0);
231 strncpy(ifr.ifr_name, name, IFNAMSIZ-1);
232 ifr.ifr_name[IFNAMSIZ-1] = 0;
233 ifr.ifr_addr.sa_family = AF_INET;
235 len = min(
sizeof(sockaddr), addr.sockaddr_len());
237 sa = addr.sockaddr();
238 memcpy(&ifr.ifr_addr, sa, len);
240 if (ioctl(sock, SIOCSIFADDR, &ifr))
242 if (errno != EACCES && errno != EPERM)
250 if (addr.
base() != none)
252 sa = addr.netmask().sockaddr();
253 memcpy(&ifr.ifr_netmask, sa, len);
255 if (ioctl(sock, SIOCSIFNETMASK, &ifr))
257 if (errno != EACCES && errno != EPERM)
263 if (!strchr(name,
':'))
265 sa = addr.broadcast().sockaddr();
266 memcpy(&ifr.ifr_broadaddr, sa, len);
268 if (ioctl(sock, SIOCSIFBRDADDR, &ifr))
270 if (errno != EACCES && errno != EPERM)
290 int retval =
req(SIOCSIFMTU, &ifr);
291 if (retval && retval != EACCES && retval != EPERM)
300 sockaddr *saddr = addr.sockaddr();
301 memcpy(& ifr.ifr_hwaddr, saddr, addr.sockaddr_len());
308 int retval =
req(SIOCSIFHWADDR, &ifr);
309 if (retval && retval != EACCES && retval != EPERM)
321 void WvInterface::fill_rte(
struct rtentry *rte,
char ifname[17],
325 struct sockaddr *net, *mask, *gwaddr;
327 bool is_direct = (gw ==
WvIPAddr());
330 memset(rte, 0,
sizeof(
struct rtentry));
331 rte->rt_metric = metric + 1;
333 strncpy(ifname, name, 17);
335 rte->rt_dev = ifname;
337 len = min(
sizeof(sockaddr), dest.sockaddr_len());
339 net = dest.network().sockaddr();
340 memcpy(&rte->rt_dst, net, len);
345 mask = dest.netmask().sockaddr();
346 memcpy(&rte->rt_genmask, mask, len);
352 gwaddr = gw.sockaddr();
353 memcpy(&rte->rt_gateway, gwaddr, len);
357 rte->rt_flags = (RTF_UP
358 | (is_host ? RTF_HOST : 0)
359 | (is_direct ? 0 : RTF_GATEWAY));
363 int WvInterface::really_addroute(
const WvIPNet &dest,
const WvIPAddr &gw,
364 const WvIPAddr &src,
int metric, WvStringParm table,
370 WvString deststr(dest), gwstr(gw), metr(metric), srcstr(src);
373 const char *
const argvnosrc[] = {
374 "ip",
"route",
"add",
383 const char *
const argvsrc[] = {
384 "ip",
"route",
"add",
395 const char *
const * argv;
403 err(WvLog::Debug2,
"addroute: ");
404 for (
int i = 0; argv[i]; i++)
405 err(WvLog::Debug2,
"%s ", argv[i]);
406 err(WvLog::Debug2,
"\n");
409 checkProc.startv(*argv, argv);
413 if (checkProc.estatus != 242)
424 fill_rte(&rte, ifname, dest, gw, metric);
426 sock = socket(AF_INET, SOCK_STREAM, 0);
427 if (ioctl(sock, SIOCADDRT, &rte))
429 if (errno != EACCES && errno != EPERM && errno != EEXIST
434 name, dest,
isup()));
446 const WvIPAddr &src,
int metric, WvStringParm table)
462 really_addroute(gw, zero, zero, 255,
"default",
true);
463 ret = really_addroute(dest, gw, src, metric, table,
false);
480 int metric, WvStringParm table)
485 WvString deststr(dest), gwstr(gw), metr(metric);
486 const char *argv[] = {
487 "ip",
"route",
"del",
498 err(WvLog::Debug2,
"delroute: ");
499 for (
int i = 0; argv[i]; i++)
500 err(WvLog::Debug2,
"%s ", argv[i]);
501 err(WvLog::Debug2,
"\n");
504 checkProc.startv(*argv, (
char *
const *)argv);
508 if (!WEXITSTATUS(checkProc.estatus))
515 fill_rte(&rte, ifname, dest, gw, metric);
517 sock = socket(AF_INET, SOCK_STREAM, 0);
518 if (ioctl(sock, SIOCDELRT, &rte))
520 if (errno != EACCES && errno != EPERM && errno != EEXIST)
539 int WvInterface::addarp(
const WvIPNet &dest,
const WvAddr &hw,
bool proxy)
546 sa = dest.network().sockaddr();
547 len = min(dest.sockaddr_len(),
sizeof(ar.arp_pa));
548 memcpy(&ar.arp_pa, sa, len);
552 len = min(hw.sockaddr_len(),
sizeof(ar.arp_ha));
553 memcpy(&ar.arp_ha, sa, len);
556 sa = dest.netmask().sockaddr();
557 len = min(dest.sockaddr_len(),
sizeof(ar.arp_netmask));
558 memcpy(&ar.arp_netmask, sa, len);
561 strncpy(ar.arp_dev, name,
sizeof(ar.arp_dev));
563 ar.arp_flags = (ATF_COM | ATF_PERM
564 | (proxy ? ATF_PUBL : 0)
565 | (proxy && dest.
is_host() ? ATF_NETMASK : 0));
567 sock = socket(AF_INET, SOCK_STREAM, 0);
568 if (ioctl(sock, SIOCSARP, &ar))
570 if (errno != EACCES && errno != EPERM)
584 return !(f & (IFF_NOARP | IFF_LOOPBACK)) && (f & IFF_BROADCAST);
588 static char *find_ifname(
char *line)
590 if (!line)
return NULL;
593 while (*line==
' ') line++;
596 char *cptr = strrchr(line,
':');
607 WvInterfaceDict::WvInterfaceDict() : log(
"Net Interface",
WvLog::Info)
614 WvInterfaceDict::~WvInterfaceDict()
628 void WvInterfaceDict::update()
631 struct ifconf ifconf;
632 char buf[
sizeof(ifconf.ifc_req) * 100];
634 WvFile procdev(
"/proc/net/dev", O_RDONLY);
640 for (i.rewind(); i.next(); )
648 procdev.blocking_getline(-1); procdev.blocking_getline(-1);
651 while ((ifname = find_ifname(procdev.blocking_getline(-1))) != NULL)
659 slist.add(ifc,
true);
660 log(WvLog::Debug3,
"Found %-16s [%s]\n", ifname, ifc->
hwaddr());
671 ifconf.ifc_buf = buf;
672 ifconf.ifc_len =
sizeof(buf);
674 sock = socket(AF_INET, SOCK_STREAM, 0);
675 if (! ioctl(sock, SIOCGIFCONF, &ifconf))
677 int count, max = ifconf.ifc_len /
sizeof(ifconf.ifc_req[0]);
679 for (count = 0; count < max; count++)
681 struct ifreq &ifr = ifconf.ifc_req[count];
687 slist.add(ifc,
true);
701 static WvIPAddr bcast(
"255.255.255.255");
707 for (i.rewind(); i.next(); )
710 if (!ifc.valid)
continue;
713 || ifc.
ipaddr().broadcast() == addr)
720 return WvString::null;
724 bool WvInterfaceDict::on_local_net(
const WvIPNet &addr)
732 for (i.rewind(); i.next(); )
735 if (!ifc.valid)
continue;
747 WvInterfaceDictBase WvInterfaceDict::slist(15);
749 int WvInterface::getinfo(
struct ifreq *ifr,
int ioctl_num) {
return 0; }
750 void WvInterface::fill_rte(
struct rtentry *rte,
char *ifname,
754 WvInterface::WvInterface(WvStringParm _name) :err(
"fake") {}
755 WvInterface::~WvInterface() {}
763 void WvInterface::up(
bool enable) {}
765 void WvInterface::promisc(
bool enable) {}
769 WvStringParm table =
"default") {
return 0; }
771 int metric = 0, WvStringParm table =
"default") {
return 0; }
773 WvStringParm table =
"default") {
return 0; }
775 int metric = 0, WvStringParm table =
"default") {
return 0; }
777 int WvInterface::addarp(
const WvIPNet &proto,
const WvAddr &hw,
bool proxy)
780 WvInterfaceDict::WvInterfaceDict() :log(
"fake") {}
781 WvInterfaceDict::~WvInterfaceDict() {}
783 void WvInterfaceDict::update() {}
784 bool WvInterfaceDict::islocal(
const WvAddr &addr) {
return true; }
785 bool WvInterfaceDict::on_local_net(
const WvIPNet &addr) {
return true; }