Watt-32 tcp/ip  2.2 dev-rel.10
ioctl.c
Go to the documentation of this file.
1 
5 /* BSD sockets functionality for Watt-32 TCP/IP
6  *
7  * Copyright (c) 1997-2002 Gisle Vanem <gvanem@yahoo.no>
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  * must display the following acknowledgement:
19  * This product includes software developed by Gisle Vanem
20  * Bergen, Norway.
21  *
22  * THIS SOFTWARE IS PROVIDED BY ME (Gisle Vanem) AND CONTRIBUTORS ``AS IS''
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED. IN NO EVENT SHALL I OR CONTRIBUTORS BE LIABLE FOR ANY
26  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Version
34  *
35  * 0.5 : Dec 18, 1997 : G. Vanem - created
36  */
37 
38 #define BSD /* in order to include SIOxx macros in <sys/ioctl.h> */
39 
40 #include "socket.h"
41 
42 #if defined(USE_BSD_API)
43 
44 static int file_ioctrl (Socket *socket, long cmd, char *argp);
45 static int iface_ioctrl (Socket *socket, long cmd, char *argp);
46 static int arp_ioctrl (Socket *socket, long cmd, char *argp);
47 static int waterm_ioctrl(Socket *socket, long cmd, char *argp);
48 
49 #define NO_CMD(cmd) SOCK_DEBUGF ((", unsupported cmd %d, group %c", \
50  (int)((cmd) & IOCPARM_MASK), \
51  (char)IOCGROUP(cmd)))
52 #ifdef USE_DEBUG
53 static const char *get_ioctl_cmd (long cmd);
54 #endif
55 
56 #ifndef NUM_IFACES
57 #define NUM_IFACES 1
58 #endif
59 
60 #ifndef ARPHRD_FDDI
61 #define ARPHRD_FDDI 10
62 #endif
63 
64 int W32_CALL ioctlsocket (int s, long cmd, char *argp)
65 {
67 
68  SOCK_PROLOGUE (socket, "\nioctlsocket:%d", s);
69 
70  SOCK_DEBUGF ((", %s", get_ioctl_cmd(cmd)));
71 
72  switch (IOCGROUP(cmd))
73  {
74  case 'f':
75  return file_ioctrl (socket, cmd, argp);
76 
77  case 'I':
78  return iface_ioctrl (socket, cmd, argp);
79 
80  case 's':
81  return waterm_ioctrl (socket, cmd, argp);
82 
83  default:
84  NO_CMD (cmd);
85  SOCK_ERRNO (ESOCKTNOSUPPORT);
86  }
87  return (-1);
88 }
89 
90 /*
91  * IO-control for "file" handles (i.e. stream/datagram sockets)
92  */
93 static int file_ioctrl (Socket *socket, long cmd, char *argp)
94 {
95  int len;
96 
97  VERIFY_RW (argp, sizeof(*argp));
98 
99  switch ((DWORD)cmd)
100  {
101  case FIONREAD:
102  if (socket->so_type != SOCK_DGRAM &&
103  socket->so_type != SOCK_STREAM)
104  {
105  SOCK_ERRNO (EBADF);
106  return (-1);
107  }
108  if (socket->so_type == SOCK_DGRAM)
109  {
110  if (socket->so_state & SS_PRIV)
111  len = sock_recv_used ((sock_type*)socket->udp_sock);
112  else len = sock_rbused ((sock_type*)socket->udp_sock);
113  }
114  else
115  len = sock_rbused ((sock_type*)socket->tcp_sock);
116 
117  if (len < 0)
118  {
119  SOCK_ERRNO (EBADF);
120  return (-1);
121  }
122 
123  SOCK_DEBUGF ((" %d", len));
124  if (len >= 0)
125  *(u_long*)argp = len;
126  break;
127 
128  case FIONBIO: /* set nonblocking I/O on/off */
129  if (*argp)
130  {
131  socket->so_state |= SS_NBIO;
132  socket->timeout = 0;
133  if (socket->tcp_sock)
134  socket->tcp_sock->timeout = 0;
135  }
136  else
137  {
138  socket->so_state &= ~SS_NBIO;
139  if (socket->tcp_sock) /* Only TCP sockets timeout on inactivety */
140  socket->timeout = sock_delay;
141  }
142  SOCK_DEBUGF ((" %d", (socket->so_state & SS_NBIO) ? 1 : 0));
143  break;
144 
145 #if 0
146  case FIOASYNC:
147  case FIOCLEX:
148  case FIONCLEX:
149  case FIONREAD:
150  case FIOSETOWN:
151  case FIOGETOWN:
152 #endif
153 
154  default:
155  NO_CMD (cmd);
156  SOCK_ERRNO (ESOCKTNOSUPPORT);
157  return (-1);
158  }
159  return (0);
160 }
161 
162 /*
163  * Return name of this interface.
164  * We only support a single interface at a time.
165  */
166 static char eth_ifname [IFNAMSIZ] = "eth0";
167 static char arc_ifname [IFNAMSIZ] = "arch0";
168 static char tok_ifname [IFNAMSIZ] = "tr0";
169 static char fddi_ifname[IFNAMSIZ] = "fddi0";
170 static char ppp_ifname [IFNAMSIZ] = "ppp0";
171 static char slp_ifname [IFNAMSIZ] = "slp0";
172 
173 void __get_ifname (char *if_name)
174 {
175  switch (_pktdevclass)
176  {
177  case PDCLASS_ETHER:
178  strcpy (if_name, eth_ifname);
179  break;
180  case PDCLASS_TOKEN:
181  strcpy (if_name, tok_ifname);
182  break;
183  case PDCLASS_FDDI:
184  strcpy (if_name, fddi_ifname);
185  break;
186  case PDCLASS_ARCNET:
187  strcpy (if_name, arc_ifname);
188  break;
189  case PDCLASS_SLIP:
190  strcpy (if_name, slp_ifname);
191  break;
192  case PDCLASS_PPP:
193  strcpy (if_name, ppp_ifname);
194  break;
195  default:
196  strcpy (if_name, "??");
197  break;
198  }
199 }
200 
201 #ifdef NOT_USED_YET
202 /*
203  * Set a new name for this interface.
204  */
205 void __set_ifname (const char *if_name)
206 {
207  switch (_pktdevclass)
208  {
209  case PDCLASS_ETHER:
210  strcpy (eth_ifname, if_name);
211  break;
212  case PDCLASS_TOKEN:
213  strcpy (tok_ifname, if_name);
214  break;
215  case PDCLASS_FDDI:
216  strcpy (fddi_name, if_ifname);
217  break;
218  case PDCLASS_ARCNET:
219  strcpy (arc_name, if_ifname);
220  break;
221  case PDCLASS_SLIP:
222  strcpy (slp_ifname, if_name);
223  break;
224  case PDCLASS_PPP:
225  strcpy (ppp_ifname, if_name);
226  break;
227  default:
228  break;
229  }
230 }
231 
232 static struct ifnet *eth_ifnet (void)
233 {
234  static struct ifnet net;
235 
237  return (&net);
238 }
239 
240 static struct ifnet *tok_ifnet (void)
241 {
242  static struct ifnet net;
243 
245  return (&net);
246 }
247 #endif
248 
249 /*
250  * Handler for interface request get/set commands
251  */
252 static int iface_ioctrl (Socket *socket, long cmd, char *argp)
253 {
254  struct ifreq *ifr = (struct ifreq *) argp;
255  struct ifconf *ifc = (struct ifconf*) argp;
256  struct sockaddr_in *sin;
257  const eth_address *eth;
258  int len, i;
259 
260  VERIFY_RW (argp, sizeof(*ifr));
261 
262  switch ((DWORD)cmd)
263  {
264  case SIOCSARP:
265  case SIOCGARP:
266  case SIOCDARP:
267  return arp_ioctrl (socket, cmd, argp);
268 
269  case SIOCGIFADDR: /* get interface address */
270  case OSIOCGIFADDR:
271  __get_ifname (ifr->ifr_name);
272 
273  if (ifr->ifr_addr.sa_family == AF_INET)
274  {
275  struct sockaddr_in *sin = (struct sockaddr_in*) &ifr->ifr_addr;
276  sin->sin_addr.s_addr = htonl (my_ip_addr);
277  break;
278  }
279 #if defined(USE_IPV6)
280  if (ifr->ifr_addr.sa_family == AF_INET6)
281  {
282  struct sockaddr_in6 *sin = (struct sockaddr_in6*) &ifr->ifr_addr;
283  memcpy (&sin->sin6_addr, &in6addr_my_ip, sizeof(sin->sin6_addr));
284  break;
285  }
286 #endif
287  if (_pktdevclass == PDCLASS_TOKEN || /* otherwise return MAC addr? */
288  _pktdevclass == PDCLASS_ETHER ||
289  _pktdevclass == PDCLASS_ARCNET ||
290  _pktdevclass == PDCLASS_FDDI)
291  memcpy (ifr->ifr_addr.sa_data, _eth_addr, sizeof(_eth_addr));
292  else memset (ifr->ifr_addr.sa_data, 0, sizeof(ifr->ifr_addr.sa_data));
293  break;
294 
295  case SIOCGIFMTU: /* get interface MTU */
296  ifr->ifr_mtu = _mtu;
297  break;
298 
299 #if 0
300  case SIOCGIFNAME: /* get interface name */
301  break;
302 #endif
303 
304  case SIOCSIFADDR: /* set interface address */
305  if (ifr->ifr_addr.sa_family == AF_INET)
306  {
307  sin = (struct sockaddr_in*) &ifr->ifr_addr;
308  my_ip_addr = ntohl (sin->sin_addr.s_addr);
309  break;
310  }
311 #if defined(USE_IPV6)
312  if (ifr->ifr_addr.sa_family == AF_INET6)
313  {
314  struct sockaddr_in6 *sin = (struct sockaddr_in6*) &ifr->ifr_addr;
315  memcpy ((void*)&in6addr_my_ip, &sin->sin6_addr, sizeof(in6addr_my_ip));
316  break;
317  }
318 #endif
319  eth = (const eth_address*) ifr->ifr_addr.sa_data; /* ?? */
320  if (!_eth_set_addr(eth))
321  {
322  SOCK_ERRNO (EINVAL);
323  return (-1);
324  }
325  break;
326 
327  case OSIOCGIFDSTADDR:
328  case SIOCGIFDSTADDR:
330  break;
331 
332  case SIOCSIFDSTADDR:
334  break;
335 
336  case SIOCSIFFLAGS: /* set iface flags */
337  /* Allow other socket types to do this?
338  */
339  if (socket->so_type == SOCK_PACKET)
340  {
341  BOOL rc;
342 
343  if (ifr->ifr_flags & IFF_PROMISC)
344  rc = _sock_set_promisc_rx_mode();
345  else if (ifr->ifr_flags & IFF_ALLMULTI)
346  rc = _sock_set_mcast_rx_mode();
347  else rc = _sock_set_normal_rx_mode (socket);
348  if (!rc)
349  {
350  SOCK_ERRNO (ENETDOWN);
351  return (-1);
352  }
353  }
354  break;
355 
356  case SIOCGIFFLAGS: /* get iface flags */
357  ifr->ifr_flags = 0;
358  if (_eth_is_init)
359  {
360  ifr->ifr_flags |= (IFF_UP | IFF_RUNNING);
361 
363  ifr->ifr_flags |= IFF_PROMISC;
364 
366  ifr->ifr_flags |= IFF_ALLMULTI;
367 
368  if (_pktdevclass == PDCLASS_PPP ||
369  _pktdevclass == PDCLASS_SLIP ||
370  _pktdevclass == PDCLASS_AX25)
371  ifr->ifr_flags |= IFF_POINTOPOINT;
372  else ifr->ifr_flags |= IFF_BROADCAST; /* ARCNET broadcast? */
373 
374 #if defined(USE_MULTICAST)
375  if (_multicast_on)
376  ifr->ifr_flags |= IFF_MULTICAST;
377 #endif
378  }
379  break;
380 
381  case SIOCGIFBRDADDR: /* get IP broadcast address */
382  case OSIOCGIFBRDADDR:
383  sin = (struct sockaddr_in*) &ifr->ifr_broadaddr;
384  sin->sin_addr.s_addr = htonl (my_ip_addr | ~sin_mask);
385  sin->sin_family = AF_INET;
386  __get_ifname (ifr->ifr_name);
387  break;
388 
389  case SIOCSIFBRDADDR: /* set IP broadcast address */
390  break;
391 
392  case SIOCGIFMETRIC: /* get interface metric */
393  ifr->ifr_metric = 1;
394  __get_ifname (ifr->ifr_name);
395  break;
396 
397  case SIOCSIFMETRIC:
399  break;
400 
401  case SIOCDIFADDR: /* delete interface addr */
402 #if defined(USE_IPV6)
403  if (ifr->ifr_addr.sa_family == AF_INET6)
404  {
405  memset ((void*)&in6addr_my_ip, 0, sizeof(in6addr_my_ip));
406  break;
407  }
408 #endif
409  if (ifr->ifr_addr.sa_family == AF_INET)
410  {
411  my_ip_addr = 0;
412  break;
413  }
414 
416  break;
417 
418  case SIOCAIFADDR:
420  break;
421 
422  case SIOCGIFNETMASK: /* get interface net-mask */
423  case OSIOCGIFNETMASK:
424  sin = (struct sockaddr_in*) &ifr->ifr_addr;
425  sin->sin_addr.s_addr = htonl (sin_mask);
426  sin->sin_family = AF_INET;
427  __get_ifname (ifr->ifr_name);
428  break;
429 
430  case SIOCSIFNETMASK: /* set interface net-mask */
431  sin = (struct sockaddr_in*) &ifr->ifr_addr;
432  sin_mask = ntohl (sin->sin_addr.s_addr);
433  break;
434 
435  case SIOCGIFCONF: /* get interfaces config */
436  case OSIOCGIFCONF:
437  len = ifc->ifc_len = min (ifc->ifc_len, NUM_IFACES*SIZEOF(*ifr));
438  ifc = (struct ifconf*) ifc->ifc_buf; /* user's buffer */
439  VERIFY_RW (ifc, len);
440 
441  i = 0;
442  for (ifr = (struct ifreq*)ifc; i < len; ifr++, i += sizeof(*ifr))
443  {
444  __get_ifname (ifr->ifr_name);
445  sin = (struct sockaddr_in*) &ifr->ifr_addr;
446  sin->sin_addr.s_addr = htonl (my_ip_addr);
447  sin->sin_family = AF_INET;
448  }
449  break;
450 
451  case SIOCGIFHWADDR:
452  switch (_pktdevclass)
453  {
454  case PDCLASS_ETHER:
455  ifr->ifr_hwaddr.sa_family = ARPHRD_ETHER;
456  memcpy (ifr->ifr_hwaddr.sa_data, _eth_addr,
457  sizeof(ifr->ifr_hwaddr.sa_data));
458  break;
459  case PDCLASS_TOKEN:
460  ifr->ifr_hwaddr.sa_family = ARPHRD_TOKEN;
461  memcpy (ifr->ifr_hwaddr.sa_data, _eth_addr,
462  sizeof(ifr->ifr_hwaddr.sa_data));
463  break;
464  case PDCLASS_FDDI:
465  ifr->ifr_hwaddr.sa_family = ARPHRD_FDDI;
466  memcpy (ifr->ifr_hwaddr.sa_data, _eth_addr,
467  sizeof(ifr->ifr_hwaddr.sa_data));
468  break;
469  case PDCLASS_ARCNET:
470  ifr->ifr_hwaddr.sa_family = ARPHRD_ARCNET;
471  ifr->ifr_hwaddr.sa_data[0] = _eth_addr[0];
472  break;
473  case PDCLASS_SLIP:
474  case PDCLASS_PPP:
475  ifr->ifr_hwaddr.sa_family = 0;
476  memset (ifr->ifr_hwaddr.sa_data, 0,
477  sizeof(ifr->ifr_hwaddr.sa_data));
478  break;
479  default:
480  return (-1);
481  }
482  break;
483 
484  default:
485  NO_CMD (cmd);
486  SOCK_ERRNO (ESOCKTNOSUPPORT);
487  return (-1);
488  }
489  ARGSUSED (len);
490  return (0);
491 }
492 
493 
494 /*
495  * Handler for buffer hi/lo watermark and urgent data (OOB)
496  */
497 static int waterm_ioctrl (Socket *socket, long cmd, char *argp)
498 {
499  VERIFY_RW (argp, sizeof(*argp));
500 
501  switch ((DWORD)cmd)
502  {
503  case SIOCSHIWAT:
505  break;
506 
507  case SIOCGHIWAT:
509  break;
510 
511  case SIOCSLOWAT:
513  break;
514 
515  case SIOCGLOWAT:
517  break;
518 
519  case SIOCATMARK:
521  break;
522 
523  default:
524  NO_CMD (cmd);
525  SOCK_ERRNO (ESOCKTNOSUPPORT);
526  return (-1);
527  }
528  ARGSUSED (socket);
529  ARGSUSED (argp);
530  return (0);
531 }
532 
533 
534 /*
535  * Handler for ARP-cache interface commands
536  */
537 static int arp_ioctrl (Socket *socket, long cmd, char *argp)
538 {
539  struct arpreq *arp = (struct arpreq*) argp;
540  eth_address *eth;
541  DWORD ip;
542 
543  switch ((DWORD)cmd)
544  {
545  case SIOCSARP: /* add given IP/MAC-addr pair to ARP cache */
546  ip = intel (*(DWORD*)arp->arp_pa.sa_data);
547  eth = (eth_address*) arp->arp_ha.sa_data;
548  if (!_arp_cache_add (ip, (const eth_address*)eth, FALSE))
549  {
550  SOCK_ERRNO (EINVAL);
551  return (-1);
552  }
553  break;
554 
555  case SIOCGARP: /* return ARP entry for given ip */
556  case OSIOCGARP:
557  ip = intel (*(DWORD*)arp->arp_pa.sa_data);
558  eth = (eth_address*) arp->arp_ha.sa_data;
559  if (_arp_lookup_fixed (ip, eth))
560  {
561  arp->arp_flags |= (ATF_INUSE | ATF_COM | ATF_PERM); /* fixed addr */
562  }
563  else if (_arp_lookup (ip, eth))
564  {
565  arp->arp_flags |= (ATF_INUSE | ATF_COM); /* dynamic addr */
566  }
567  else
568  {
569  arp->arp_flags = 0;
570  SOCK_ERRNO (ENOENT);
571  return (-1);
572  }
573  break;
574 
575  case SIOCDARP: /* delete ARP-entry for given ip */
576  ip = intel (*(DWORD*)arp->arp_pa.sa_data);
577  if (!_arp_cache_del(ip))
578  {
579  SOCK_ERRNO (ENOENT);
580  return (-1);
581  }
582  break;
583 
584  default:
585  NO_CMD (cmd);
586  SOCK_ERRNO (ESOCKTNOSUPPORT);
587  return (-1);
588  }
589  ARGSUSED (socket);
590  return (0);
591 }
592 
593 /*
594  * Return string for ioctlsocket() command
595  */
596 #if defined(USE_DEBUG)
597 static const struct search_list commands[] = {
598  { FIOCLEX, "FIOCLEX" },
599  { FIONCLEX, "FIONCLEX" },
600  { FIONREAD, "FIONREAD" },
601  { FIONBIO, "FIONBIO" },
602  { FIOASYNC, "FIOASYNC" },
603  { FIOSETOWN, "FIOSETOWN" },
604  { FIOGETOWN, "FIOGETOWN" },
605  { SIOCSPGRP, "SIOCSPGRP" },
606  { SIOCGPGRP, "SIOCGPGRP" },
607  { SIOCADDRT, "SIOCADDRT" },
608  { SIOCDELRT, "SIOCDELRT" },
609  { SIOCSIFADDR, "SIOCSIFADDR" },
610  { OSIOCGIFADDR, "OSIOCGIFADDR" },
611  { SIOCGIFADDR, "SIOCGIFADDR" },
612  { SIOCSIFDSTADDR, "SIOCSIFDSTADDR" },
613  { OSIOCGIFDSTADDR, "OSIOCGIFDSTADDR" },
614  { SIOCGIFDSTADDR, "SIOCGIFDSTADDR" },
615  { SIOCSIFFLAGS, "SIOCSIFFLAGS" },
616  { SIOCGIFFLAGS, "SIOCGIFFLAGS" },
617  { OSIOCGIFBRDADDR, "OSIOCGIFBRDADDR" },
618  { SIOCGIFBRDADDR, "SIOCGIFBRDADDR" },
619  { SIOCSIFBRDADDR, "SIOCSIFBRDADDR" },
620  { OSIOCGIFCONF, "OSIOCGIFCONF" },
621  { SIOCGIFCONF, "SIOCGIFCONF" },
622  { OSIOCGIFNETMASK, "OSIOCGIFNETMASK" },
623  { SIOCGIFNETMASK, "SIOCGIFNETMASK" },
624  { SIOCSIFNETMASK, "SIOCSIFNETMASK" },
625  { SIOCGIFMETRIC, "SIOCGIFMETRIC" },
626  { SIOCSIFMETRIC, "SIOCSIFMETRIC" },
627  { SIOCDIFADDR, "SIOCDIFADDR" },
628  { SIOCAIFADDR, "SIOCAIFADDR" },
629  { SIOCGIFMTU, "SIOCGIFMTU" },
630  { SIOCSARP, "SIOCSARP" },
631  { OSIOCGARP, "OSIOCGARP" },
632  { SIOCGARP, "SIOCGARP" },
633  { SIOCDARP, "SIOCDARP" },
634  { SIOCSHIWAT, "SIOCSHIWAT" },
635  { SIOCGHIWAT, "SIOCGHIWAT" },
636  { SIOCSLOWAT, "SIOCSLOWAT" },
637  { SIOCGLOWAT, "SIOCGLOWAT" },
638  { SIOCATMARK, "SIOCATMARK" },
639  { SIOCGIFHWADDR, "SIOCGIFHWADDR" }
640  };
641 
642 static const char *get_ioctl_cmd (long cmd)
643 {
644  static char buf[50];
645 
646  switch (IOCGROUP(cmd))
647  {
648  case 'f':
649  strcpy (buf, "file cmd: ");
650  break;
651 
652  case 'I':
653  strcpy (buf, "iface cmd: ");
654  break;
655 
656  case 's':
657  strcpy (buf, "waterm cmd: ");
658  break;
659 
660  default:
661  return ("??unknown");
662  }
663  strcat (buf, list_lookup(cmd, commands, DIM(commands)));
664  return (buf);
665 }
666 #endif
667 
668 
669 /*
670  * A small test program for above functions.
671  */
672 #if defined(TEST_PROG)
673 
674 #undef assert
675 #define assert(x) ((x) ? (void)0 : __assert_fail(__LINE__))
676 
677 void __assert_fail (unsigned line)
678 {
679  fprintf (stderr, "\nAssert failed at line %d, errno = %d (%s)\n",
680  line, errno, strerror(errno));
681  exit (-1);
682 }
683 
684 const char *eth_addr_string (struct ether_addr *eth)
685 {
686  static char buf[20];
687 
688  sprintf (buf, "%02X:%02X:%02X:%02X:%02X:%02X",
689  eth->ether_addr_octet[0],
690  eth->ether_addr_octet[1],
691  eth->ether_addr_octet[2],
692  eth->ether_addr_octet[3],
693  eth->ether_addr_octet[4],
694  eth->ether_addr_octet[5]);
695  return (buf);
696 }
697 
698 const char *if_flags_string (unsigned short flags)
699 {
700  static char buf[200];
701 
702  buf[0] = '\0';
703 
704  if (flags & IFF_UP)
705  strcat (buf,"up,");
706  if (flags & IFF_BROADCAST)
707  strcat (buf,"broadcast,");
708  if (flags & IFF_DEBUG)
709  strcat (buf,"debug,");
710  if (flags & IFF_LOOPBACK)
711  strcat (buf,"loopback,");
712  if (flags & IFF_POINTOPOINT)
713  strcat (buf,"p-to-p,");
714  if (flags & IFF_NOTRAILERS)
715  strcat (buf,"no-trail,");
716  if (flags & IFF_RUNNING)
717  strcat (buf,"running,");
718  if (flags & IFF_NOARP)
719  strcat (buf,"no-arp,");
720  if (flags & IFF_PROMISC)
721  strcat (buf,"promisc,");
722  if (flags & IFF_ALLMULTI)
723  strcat (buf,"all-multi,");
724  if (flags & IFF_OACTIVE)
725  strcat (buf,"out-act,");
726  if (flags & IFF_SIMPLEX)
727  strcat (buf,"simplex,");
728  if (flags & IFF_LINK0)
729  strcat (buf,"link0,");
730  if (flags & IFF_LINK1)
731  strcat (buf,"link1,");
732  if (flags & IFF_LINK2)
733  strcat (buf,"link2,");
734  if (flags & IFF_MULTICAST)
735  strcat (buf,"mcast,");
736 
737  if (buf[0])
738  buf[strlen(buf)-1] = '\0';
739  return (buf);
740 }
741 
742 int main (void)
743 {
744  struct ifreq ifr;
745  struct sockaddr_in *sin;
746  int sock, on = 1;
747 
748  dbug_init();
749 
750  sock = socket (AF_INET, SOCK_DGRAM, 0);
751  assert (sock > 0);
752  assert (setsockopt(sock, SOL_SOCKET, SO_DEBUG, &on,sizeof(on)) == 0);
753 
754  ifr.ifr_addr.sa_family = AF_UNSPEC; /* get MAC-address */
755 
756  assert (ioctlsocket (sock, SIOCGIFADDR, (char*)&ifr) == 0);
757  printf ("Interface `%s':\n\t ether-addr: %s\n",
758  ifr.ifr_name,
759  eth_addr_string ((struct ether_addr*)&ifr.ifr_hwaddr.sa_data));
760 
761  assert (ioctlsocket (sock, SIOCGIFBRDADDR, (char*)&ifr) == 0);
762  sin = (struct sockaddr_in*) &ifr.ifr_broadaddr;
763  printf ("\t bcast-addr: %s\n", inet_ntoa (sin->sin_addr));
764 
765  ifr.ifr_addr.sa_family = AF_INET;
766 
767  assert (ioctlsocket (sock, SIOCGIFADDR, (char*)&ifr) == 0);
768  sin = (struct sockaddr_in*) &ifr.ifr_addr;
769  printf ("\t inet-addr: %s\n", inet_ntoa (sin->sin_addr));
770 
771  assert (ioctlsocket (sock, SIOCGIFNETMASK, (char*)&ifr) == 0);
772  sin = (struct sockaddr_in*) &ifr.ifr_addr;
773  printf ("\t net-mask : %s\n", inet_ntoa (sin->sin_addr));
774 
775  assert (ioctlsocket (sock, SIOCGIFMTU, (char*)&ifr) == 0);
776  printf ("\t MTU : %u\n",ifr.ifr_mtu);
777 
778  assert (ioctlsocket (sock, SIOCGIFFLAGS, (char*)&ifr) == 0);
779  printf ("\t Flags : 0x%04X: %s\n",
780  ifr.ifr_flags, if_flags_string(ifr.ifr_flags));
781 
782  assert (close_s(sock) >= 0);
783  return (0);
784 }
785 
786 #endif /* TEST_PROG */
787 #endif /* USE_BSD_API */
BOOL W32_CALL _arp_cache_add(DWORD ip, const void *eth, BOOL expires)
Add given IP/Ether address to ARP-cache.
Definition: pcarp.c:1352
Definition: socket.h:137
Definition: if.h:84
static int waterm_ioctrl(Socket *socket, long cmd, char *argp)
Definition: ioctl.c:497
const char * list_lookup(DWORD type, const struct search_list *list, int num)
Search 'list' for 'type' and return it's name.
Definition: misc.c:929
mac_address _eth_addr
Local link-layer source address.
Definition: pcsed.c:50
static int iface_ioctrl(Socket *socket, long cmd, char *argp)
Definition: ioctl.c:252
Socket * _socklist_find(int s)
Returns a pointer to the Socket structure associated with socket 's'.
Definition: socket.c:1534
DWORD sin_mask
our net-mask, 255.255.255.0
Definition: pctcp.c:71
BOOL W32_CALL _arp_lookup_fixed(DWORD ip, eth_address *eth)
Lookup fixed MAC-address of 'ip'.
Definition: pcarp.c:1219
BOOL W32_CALL _arp_lookup(DWORD ip, eth_address *eth)
Lookup MAC-address of 'ip'.
Definition: pcarp.c:1186
Definition: ip.h:67
Definition: if.h:130
WORD _pktdevclass
Ethernet, Token, FDDI etc.
Definition: pcpkt.c:51
int W32_CALL socket(int family, int type, int protocol)
socket().
Definition: socket.c:1794
BOOL W32_CALL _arp_cache_del(DWORD ip)
Delete given 'ip' address from ARP-cache (dynamic, fixed or pending).
Definition: pcarp.c:1421
static struct ifnet * eth_ifnet(void)
Definition: ioctl.c:232
static struct ifnet * tok_ifnet(void)
Definition: ioctl.c:240
BROADCAST + all multicast.
Definition: pcpkt.h:113
BOOL _eth_is_init
we are initialised
Definition: pcsed.c:55
Definition: if.h:345
receive all packets on network
Definition: pcpkt.h:114
DWORD my_ip_addr
our IP address
Definition: pctcp.c:70
int _pkt_rxmode
active receive mode
Definition: pcpkt.c:56
Definition: if.h:298
int W32_CALL _eth_set_addr(const void *addr)
Sets a new MAC address for our interface.
Definition: pcsed.c:731
DWORD timeout
timer for retrans etc.
Definition: wattcp.h:631
int main(int argc, char **argv)
Definition: echo.c:223
Definition: if_arp.h:102