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;
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)
170 err.perror(
WvString(
"SetFlags %s", name));
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)
204 err.perror(
WvString(
"Set PointoPoint %s", name));
208 return setflags(IFF_POINTOPOINT, enable ? IFF_POINTOPOINT : 0);
214 return (getflags() & IFF_PROMISC) ? 1 : 0;
226 if (addr != ipaddr())
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)
243 err.perror(
WvString(
"SetIfAddress %s", name));
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)
258 err.perror(
WvString(
"SetNetmask %s", name));
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)
271 err.perror(
WvString(
"SetBroadcast %s", name));
290 int retval = req(SIOCSIFMTU, &ifr);
291 if (retval && retval != EACCES && retval != EPERM)
292 err.perror(
WvString(
"SetMTU %s", name));
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)
310 err.perror(
WvString(
"SetHWAddr %s", name));
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,
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
433 err.perror(
WvString(
"AddRoute '%s' %s (up=%s)",
434 name, dest, isup()));
462 really_addroute(gw, zero, zero, 255,
"default",
true);
463 ret = really_addroute(dest, gw, src, metric, table,
false);
465 delroute(gw, zero, 255,
"default");
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)
521 err.perror(
WvString(
"DelRoute %s", name));
534 return delroute(dest,
WvIPAddr(), metric, table);
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)
571 err.perror(
WvString(
"AddARP %s", name));
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) {}
771 int metric = 0,
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; }
A WvFastString acts exactly like a WvString, but can take (const char *) strings without needing to a...
const WvAddr & hwaddr()
get the hardware address of this interface
WvFile implements a stream connected to a file or Unix device.
int req(int ioctl_num, struct ifreq *ifr)
get/set information about an interface
int ptp(bool enable, const WvIPNet &addr)
turn point-to-point mode on or off.
int getflags()
get the current kernel flags
An IP address is made up of a "dotted quad" – four decimal numbers in the form www.xxx.yyy.zzz.
const WvIPNet & ipaddr()
get the local IP net of this interface
int setflags(int clear, int set)
toggle kernel flags on this netdevice.
void rescan()
forget all stored information about the address(es) of this interface
int setmtu(int mtu)
Sets the MTU of the interface.
int addroute(const WvIPNet &dest, int metric=0, WvStringParm table="default")
add a route to the given network through this interface.
int sethwaddr(const WvAddr &addr)
Set the hardware address of this interface.
const WvIPAddr dstaddr()
get the point-to-point IP address of this interface
A WvAddr that simply contains a printable string with a user-defined encapsulation type...
bool is_host() const
is it a plain host? (x.x.x.x/32)
A WvInterface manages a particular network interface.
WvLog split(LogLevel _loglevel) const
split off a new WvLog object with the requested loglevel.
Base class for different address types, each of which will have the ability to convert itself to/from...
bool is_default() const
is this net the default gateway? (0.0.0.0/0)
WvIPAddr base() const
Get the 'base IP address' component, netmask, network, and broadcast.
int delroute(const WvIPNet &dest, int metric=0, WvStringParm table="default")
delete a route to the given network through this interface.
WvString is an implementation of a simple and efficient printable-string class.
virtual const WvAddr * src() const
get the remote address from which the last data block was received.
bool isarp()
add an ARP entry on this interface
int setipaddr(const WvIPNet &addr)
Sets the local address, netmask, and broadcast of this interface and set a route to the local net...
A WvLog stream accepts log messages from applications and forwards them to all registered WvLogRcv's...
int bits() const
weird netmasks such as 255.0.255.0 (easy example) are almost never used – they have '0' bits in the...
An IP network comprises two WvIPAddr structures: an address and a netmask.
bool ispromisc()
turn promiscuous (see-all-packets) mode on or off.
bool isup()
set the interface state up or down.
virtual void close()
Close this stream.
bool includes(const WvIPNet &addr) const
determine whether the given address is already included in this net