#ifndef SML3__NW_IF_H_
#define SML3__NW_IF_H_

/* ++++++++++++++++++++
 * +++ Beschreibung +++
 * ++++++++++++++++++++

  Funktionen zum Erhalt der Netzwerk-Schnittstellen
+++ */


/* ++++++++++++++++
 * +++ Beispiel +++
 * ++++++++++++++++

  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  #include <sys/types.h>
  #include <unistd.h>
  #include <errno.h>
  #include <sammel3.h>

  int main(int argc, char **argv) {
    struct SML3_nw_if *ifi, *ifihead;
    int doaliases = 1;  // doaliases = <0|1>
    int family = 4; // family = <4 | 6 | 0>

    ifihead = SML3_nw_if_get(family, doaliases);
    if (ifihead == NULL) {
      if (SML3_fehlererrno() == 0) {
        exit(0);
      } else {
        fprintf(stderr, "%s\n", SML3_fehlermsg());
        exit(1);
      }
    }
      
    for (ifi = ifihead; ifi != NULL; ifi = ifi->next) {
      // Schnittstellenname mit Parametern
      if (ifi->index > 0) { printf("%d: ", ifi->index); }
      printf("%s <", ifi->name);  // interface name
      if (ifi->flags & IFF_UP) { printf("UP "); }  // interface is up
      if (ifi->flags & IFF_BROADCAST) { printf("BCAST "); }  // supports broadcast
      if (ifi->flags & IFF_MULTICAST) { printf("MCAST "); }  // supports multicast
      if (ifi->flags & IFF_LOOPBACK) { printf("LOOP "); }  // loopback interface
      if (ifi->flags & IFF_POINTOPOINT) { printf("P2P "); }  // PPP interface
      printf(">\n");

      // Hardwareaddresse
      if (*ifi->hwaddr != '\0') {
        printf("  HWaddr: %s\n", ifi->hwaddr);
      }

      // MTU
      if (ifi->mtu != 0) { printf("  MTU: %d\n", ifi->mtu); }

      // Internetadresse
      if (*ifi->nwaddr != '\0') {
        if (ifi->alias) { printf("  Alias-Adresse: "); } else { printf("  Adresse: "); }
        printf("%s\n", ifi->nwaddr);
      }

      // Broadcastadresse
      if (*ifi->brdaddr != '\0') {
        printf("  Broadcast: %s\n", ifi->brdaddr);
      }

      // Destinationadresse
      if (*ifi->dstaddr != '\0') {
        printf("  Destination: %s\n", ifi->dstaddr);
      }

      // Netzmaske
      if (*ifi->netmask != '\0') {
        printf("  Netmask: %s\n", ifi->netmask);
      }
      printf("\n");
    }

    SML3_nw_if_free(ifihead);
    exit(0);
  }
+++ */


/* ++++++++++++++++++ */
/* +++ Funktionen +++ */
/* ++++++++++++++++++ */

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <net/if.h>

#define SML3_NW_IF_HALEN  8     /* allow for 64-bit EUI-64 in future */
#define IFI_ALIAS 1             /* ifi_addr is an alias */
#ifdef IFNAMSIZ
# define SML3_NW_IF_NAMSIZE  IFNAMSIZ
#else
# define SML3_NW_IF_NAMSIZE  32
#endif
#ifdef INET6_ADDRSTRLEN
# define SML3_NW_IF_ADDRLEN INET6_ADDRSTRLEN
#else
# define SML3_NW_IF_ADDRLEN 64
#endif

struct SML3_nw_if {
  struct SML3_nw_if *next;                /* naechstes Listenelement */
  int family;                             /* 4 oder 6 (oder 0) */
  int mtu;                                /* Interface-MTU */
  int flags;                              /* IFF_* Konstanten aus <net/if.h> */
  short index;                            /* Interface-Index */
  short alias;                            /* ob Alias-Adresse */
  char name[SML3_NW_IF_NAMSIZE + 1];      /* Interface-Name */
  char hwaddr[3 * SML3_NW_IF_HALEN + 1];  /* Hardware-Adresse oder leer */
  char nwaddr[SML3_NW_IF_ADDRLEN + 1];    /* Netzwerk-Adresse oder leer */
  char brdaddr[SML3_NW_IF_ADDRLEN + 1];   /* Broadcast-Adresse oder leer */
  char dstaddr[SML3_NW_IF_ADDRLEN + 1];   /* Ziel-Adresse oder leer */
  char netmask[SML3_NW_IF_ADDRLEN + 1];   /* Netzmaske oder leer */
  int cidr;                               /* CIDR oder 0 */
};


/** SML3_nw_if_get [thread-sicher]:
 * Netzwerk-Schnittstellen erhalten
 * 1.Arg: family: 4 (=IPv4) oder 6 (=IPv6) oder 0 (=alles)
 * 2.Arg: 0 = ohne Aliase oder 1 = mit Aliasen
 * Rueckgabe: verkettete Liste mit Schnittstellen
 *            oder NULL:
 *             - SML3_fehlererrno() = 0: keine Schnittstellen
 *             - ansonsten: Fehler
 * SML3-errno-Wert: EINVAL = Fehler Uebergabeparameter
 *                  ENOMEM = Allokationsfehler
 *                  ENOTCONN = Socket nicht erhalten
 *                  ENXIO = Fehler Erhalt NW-Schnittstellen
 */
extern struct SML3_nw_if * SML3_nw_if_get(int, int);


/** SML3_nw_if_free [thread-sicher]:
 * gibt 1.Arg frei
 * 1.Arg: mit SML3_nw_if_get() erhaltene Schnittstellenliste
 */
extern void SML3_nw_if_free(struct SML3_nw_if *);

#endif /* SML3__NW_IF_H_ */
