Solaris: How to create new logical interfaces

Adding a new logical interface in Solaris is easy once you know which structures you must used (and how to fill them). I hope this page will be helpfull …

This code is not very clean, it's more a Proof Of Concept than a production code.

int
main (int argc, char *argv[])
{
   int errors = 0;
 
   errors += add_if("nge0", "192.168.1.1");
 
   return errors;
}
 
/* Add a new virtual interface with address */
int
add_if(char *device, char *address)
{
   int s = -1;
   int ret = 1;
   struct lifreq lifr;
   int prefixlen;
   struct sockaddr_storage laddr;
 
   if (strchr(device, ':') != NULL) {
      (void) fprintf(stderr,
          "ifconfig: addif: bad physical interface name %s\n",
          device);
      goto error;
   }
 
   memset(&laddr, 0, sizeof(laddr));
   memset(&lifr, 0, sizeof(lifr));
 
   in_getaddr(address, (struct sockaddr *) &laddr);
 
   /* Quoted from OpenSolaris's ifconfig.c
 
    * This is a "hack" to get around the problem of SIOCLIFADDIF.  The
    * problem is that this ioctl does not include the netmask when
    * adding a logical interface.  This is the same problem described
    * in the ifconfig() comments.  To get around this problem, we first
    * add the logical interface with a 0 address.  After that, we set
    * the netmask if provided.  Finally we set the interface address.
   */
 
   /* Copy the devicename */
   (void) strncpy(lifr.lifr_name, device, sizeof(lifr.lifr_name));
   (void) memset(&lifr.lifr_addr, 0, sizeof (lifr.lifr_addr));
 
   if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
   {
      perror("socket");
      goto error;
   }
 
   if (ioctl(s, SIOCLIFADDIF, (caddr_t) &lifr) < 0)
   {
      perror ("ioctl SIOCLIFADDIF");
      goto error;
   }
   printf("Created new logical interface: %s...\n", lifr.lifr_name);
 
   lifr.lifr_addr = laddr;
 
   /* Now we have our new interface, set the address */
   if (ioctl(s, SIOCSLIFADDR, (caddr_t) &lifr) < 0)
   {
      perror("ioctl SIOCSLIFADDR");
      goto error;
   }
 
   ret = 0;
 
error:
   if (s > 0)
      close(s);
 
   return ret;
}
 
/* Remove a virtual interface */
int
remove_if(char *device, char *address)
{
   return 0;
}
 
/*
 * Fill saddr structure from the address string s
 */
void
in_getaddr(char *s, struct sockaddr *saddr)
{
   struct sockaddr_in *sin = (struct sockaddr_in *) saddr;
   struct hostent *hp;
   struct netent *np;
   int error;
   char str[BUFSIZ];
 
   (void) memset(sin, 0, sizeof (*sin));
   (void) strncpy(str, s, sizeof(str));
 
   hp = getipnodebyname(str, AF_INET, 0, &error);
 
   if (!hp) {
      perror("getipnodebyname");
      return;
   }
   freehostent(hp);
 
   sin->sin_family = AF_INET;
 
   (void) memcpy(&sin->sin_addr, hp->h_addr, hp->h_length);
 
}