route.c 3.34 KB
Newer Older
Benoit Steiner's avatar
Benoit Steiner committed
1 2 3 4 5 6 7 8
/* VideoLAN VLANbridge : Kernel routing tables management
 *
 * Benoit Steiner, VIA, ECP, <benny@via.ecp.fr>
 *
 * TO DO: With ioctl request, we just can send route_add or route_del command. We should use the routing socket, but linux just support read operations at that time (see TCP/IIP Illustrated p 569-570)
*/


9 10 11 12
/* For Solaris */
#include <sys/types.h>
#include <strings.h>

Benoit Steiner's avatar
Benoit Steiner committed
13 14 15 16 17 18
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/route.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
19
#include <stdio.h>
Benoit Steiner's avatar
Benoit Steiner committed
20 21
#include <errno.h>

22
#include "debug.h"
Benoit Steiner's avatar
Benoit Steiner committed
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
#include "log.h"
#include "route.h"

/* VLANbridge module name */
#define MOD_NAME MOD_PERFORMER


/***************************************************************************/
/* Add a route in the routing table 					   */
/***************************************************************************/
int Route_Add (int iSockFd, struct sockaddr_in* psaAddr, char* strDev)
{
  int iRc = 0;
  struct rtentry rteRequest;

38 39 40
  ASSERT(psaAddr);
  ASSERT(strDev);

Benoit Steiner's avatar
Benoit Steiner committed
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
  bzero(&rteRequest, sizeof(struct rtentry));

  /* Set the flags associated to the entry */
  rteRequest.rt_flags = RTF_UP;			/* Interface is up */
  rteRequest.rt_flags |= RTF_STATIC;		/* Route was entered by hand */
  rteRequest.rt_flags |= RTF_HOST;		/* Direct route (no gateway) */
  rteRequest.rt_metric = 0;			/* Cost of the route */

  /* Set the host the route points to */
  memcpy(&rteRequest.rt_dst, psaAddr, sizeof(struct sockaddr));
  /* Set the netmask to 255.255.255.255*/
  ((struct sockaddr_in *)&rteRequest.rt_genmask)->sin_addr.s_addr = (unsigned long)-1;
  /* Set the device used to reach the destination */
  rteRequest.rt_dev = strDev;

  /* Add the route to the routing table */
  if (ioctl(iSockFd, SIOCADDRT, &rteRequest) < 0)
  {
    Log (LOG_ERROR, MOD_NAME, "Unable to add route to host %s on interface %s: %s",
         inet_ntoa(psaAddr->sin_addr), strDev, strerror(errno));
    iRc = errno;
  }

#ifdef DEBUG
  else
    Log (LOG_NOTE, MOD_NAME, "Route to host %s set to interface %s",
         inet_ntoa(psaAddr->sin_addr), strDev);
#endif

  return iRc;
};


/***************************************************************************/
/* Remove a route from the routing table 				   */
/***************************************************************************/
int Route_Del (int iSockFd, struct sockaddr_in* psaAddr, char* strDev)
{ 
  int iRc = 0;
  struct rtentry rteRequest;

82 83 84
  ASSERT(psaAddr);
  ASSERT(strDev);

Benoit Steiner's avatar
Benoit Steiner committed
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
  bzero(&rteRequest, sizeof(struct rtentry));

  /* Set the flags associated to the entry */
  rteRequest.rt_flags = RTF_UP;			/* Interface is up */
  rteRequest.rt_flags |= RTF_STATIC;		/* Route was entered by hand */
  rteRequest.rt_flags |= RTF_HOST;		/* Direct route (no gateway) */
  rteRequest.rt_metric = 0;			/* Cost of the route */

  /* Set the host the route points to */
  memcpy(&rteRequest.rt_dst, psaAddr, sizeof(struct sockaddr));
  /* Set the device used to reach the destination */
  rteRequest.rt_dev = strDev;

  /* Remove the route from the routing table */
  if (ioctl(iSockFd, SIOCDELRT, &rteRequest) < 0)
  {
    Log (LOG_ERROR, MOD_NAME, "Unable to remove route to host %s: %s",
         inet_ntoa(psaAddr->sin_addr), strerror(errno));
    iRc = errno;
  }
#ifdef DEBUG
  else
    Log (LOG_NOTE, MOD_NAME, "Route to host %s removed",
         inet_ntoa(psaAddr->sin_addr));  
#endif

  return iRc;
};