int main(int argc, char *argv[])
{
    int sockfd;
    char *buf;
    pid_t pid;
    ssize_t n;
    struct rt_msghdr *rtm;
    struct sockaddr *sa, *rti_info[RTAX_MAX];
    struct sockaddr_in *sin;

    if (argc != 2)
        err_quit("Usage: %s <IPaddress>", basename(argv[0]));

    sockfd = Socket(AF_ROUTE, SOCK_RAW, 0); /* need superuser privileges */
    buf = Calloc(1, BUFLEN); /* and initialized to 0 */

    rtm = (struct rt_msghdr *)buf;
    rtm->rtm_msglen = sizeof(struct rt_msghdr) + sizeof(struct sockaddr_in);
    rtm->rtm_version = RTM_VERSION;
    rtm->rtm_type = RTM_GET;
    rtm->rtm_addrs = RTA_DST;
    rtm->rtm_pid = pid = getpid();
    rtm->rtm_seq = SEQ;

    sin = (struct sockaddr_in *)(rtm + 1);
    sin->sin_len = sizeof(struct sockaddr_in);
    sin->sin_family = AF_INET;
    Inet_pton(AF_INET, argv[1], &sin->sin_addr); 

    Write(sockfd, rtm, rtm->rtm_msglen);

    do {
        n = Read(sockfd, rtm, BUFLEN);
    } while (rtm->rtm_type != RTM_GET || rtm->rtm_seq != SEQ ||
            rtm->rtm_pid != pid);

    rtm = (struct rt_msghdr *)buf;
    sa = (struct sockaddr *)(rtm + 1);
    get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
    if ((sa = rti_info[RTAX_DST]) != NULL)
        printf("dest: %s\n", Sock_ntop_host(sa, sa->sa_len));
    if ((sa = rti_info[RTAX_GATEWAY]) != NULL)
        printf("gateway: %s\n", Sock_ntop_host(sa, sa->sa_len));
    if ((sa = rti_info[RTAX_NETMASK]) != NULL)
        printf("netmask: %s\n", sock_masktop(sa, sa->sa_len));
    if ((sa = rti_info[RTAX_GENMASK]) != NULL)
        printf("genmask: %s\n", sock_masktop(sa, sa->sa_len));

    exit(0);
}
Exemplo n.º 2
0
// function used to configure a route to "daddr" by specifying either
// the gateway address "gaddr" or the interface name "ifname"; 
// a mask given by "maddr" can also be specified
// the command codes "cmd" indicate the type of operation
// Note: addresses are given as 4-byte words (c.f. rtctl)
int rtctl2(uint32_t *daddr,	/* destination IP address */
	   uint32_t *gaddr,	/* gateway IP address */
	   uint32_t *maddr,	/* subnet mask */
	   char *ifname,	/* network interface name */
	   u_char cmd)		/* RTM_ADD RTM_DELETE RTM_CHANGE */
{
  int sockfd, mib[6], len;
  char *buf, rta_cmd[RTCTL_CMD_LEN], *ifbuf;
  char dstaddr[16], gateaddr[16], maskaddr[16];
  u_char flag;
  pid_t pid;
  struct rt_msghdr *rtm;
  struct sockaddr_in *dst, *gate, *mask;
  struct sockaddr_dl *ifp, *sdl;
  struct if_msghdr *ifm;

#ifdef RTCTL_PRINT_RESPONSE
  ssize_t			n;
  struct sockaddr		*sa, *rti_info[RTAX_MAX];
#endif	

  /* check the arguments */
  if (daddr == NULL)
    {
      fprintf(stderr, "Invalid destination IP address\n");
      return -1;
    }
  flag = 0;
  if (cmd == RTM_ADD)
    {
      flag |= RTCTL_ADD;
      strncpy(rta_cmd, "add", sizeof("add"));
      if (gaddr == NULL)
	{
	  if (ifname == NULL)
	    flag |= RTCTL_UNKNOWN;
	  else if (maddr != NULL)
	    flag |= RTCTL_UNKNOWN;
	  else
	    flag |= RTCTL_IF;
	}
      else
	{
	  flag |= RTCTL_GATEWAY;
	  if (ifname != NULL)
	    flag |= RTCTL_UNKNOWN;
	  else if (maddr != NULL)
	    flag |= RTCTL_NETMASK;
	}
    }
  else if (cmd == RTM_DELETE)
    {
      flag |= RTCTL_DELETE;
      strncpy(rta_cmd, "delete", sizeof("delete"));
      if ((ifname != NULL) | (gaddr != NULL) | (maddr != NULL))
	flag |= RTCTL_UNKNOWN;
    }
  else if (cmd == RTM_CHANGE)
    {
      flag |= RTCTL_CHANGE;
      strncpy(rta_cmd, "change", sizeof("change"));
      if (gaddr == NULL)
	{
	  if (ifname == NULL)
	    flag |= RTCTL_UNKNOWN;
	  else if (maddr != NULL)
	    flag |= RTCTL_UNKNOWN;
	  else
	    flag |= RTCTL_IF;
	}
      else
	{
	  flag |= RTCTL_GATEWAY;
	  if (ifname != NULL)
	    flag |= RTCTL_UNKNOWN;
	  else if (maddr != NULL)
	    flag |= RTCTL_NETMASK;
	}
    }
  else
    {
      fprintf(stderr, "Invalid command name\n");
      return -1;
    }

  if (flag & RTCTL_UNKNOWN)
    {
      fprintf(stderr, "Unknown arguments are inputed.\n");
      return -1;
    }
  
  if ((buf = calloc(1, BUFLEN)) == NULL)
    {
      perror("calloc");
      return -1;
    }

  /* set address of rt messages */
  rtm = (struct rt_msghdr *) buf;
  rtm->rtm_version = RTM_VERSION;
  rtm->rtm_type = cmd;
  rtm->rtm_pid = pid = getpid();
  rtm->rtm_seq = ++rtm_seq;
  rtm->rtm_errno = 0;
  if ((flag & RTCTL_ADD) | (flag & RTCTL_CHANGE))
    {
      if (flag & RTCTL_IF)
	{
	  rtm->rtm_msglen = sizeof(struct rt_msghdr) +
	    sizeof(struct sockaddr_in) + 
	    sizeof(struct sockaddr_dl);
	  rtm->rtm_addrs = RTA_DST | RTA_GATEWAY;
	  rtm->rtm_flags = RTF_UP | RTF_HOST | RTF_LLINFO
	    | RTF_STATIC;
	}
      else if (flag & RTCTL_NETMASK)
	{
	  rtm->rtm_msglen = sizeof(struct rt_msghdr) +
	    3 * sizeof(struct sockaddr_in);
	  rtm->rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
	  rtm->rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC;
	}
      else
	{
	  rtm->rtm_msglen = sizeof(struct rt_msghdr) +
	    2 * sizeof(struct sockaddr_in);
	  rtm->rtm_addrs = RTA_DST | RTA_GATEWAY;
	  rtm->rtm_flags = RTF_UP | RTF_HOST | RTF_GATEWAY
	    | RTF_STATIC;
	}
    }
  else if (flag & RTCTL_DELETE)
    {
      rtm->rtm_msglen = sizeof(struct rt_msghdr) +
	sizeof(struct sockaddr_in);
      rtm->rtm_addrs = RTA_DST;
    }

  /* set destination RTA_GATEWAY */
  dst = (struct sockaddr_in *) (rtm + 1);
  dst->sin_len = sizeof(struct sockaddr_in);
  dst->sin_family = AF_INET;
  fflush(stderr);
  dst->sin_addr.s_addr = *daddr;
  if (flag & RTCTL_GATEWAY)
    {
      /* set gateway */
      gate = (struct sockaddr_in *) (dst + 1);
      gate->sin_len = sizeof(struct sockaddr_in);
      gate->sin_family = AF_INET;
      gate->sin_addr.s_addr = *gaddr;
      if (flag & RTCTL_NETMASK)
	{
	  mask = (struct sockaddr_in *) (gate + 1);
	  mask->sin_len = sizeof(struct sockaddr_in);
	  mask->sin_family = AF_INET;
	  mask->sin_addr.s_addr = *maddr;
	}
    }
  else if (flag & RTCTL_IF)
    {
      /* get sockaddr_dl info */
      mib[0] = CTL_NET;
      mib[1] = AF_ROUTE;
      mib[2] = 0;
      mib[3] = AF_LINK;
      mib[4] = NET_RT_IFLIST;
      if ((mib[5] = if_nametoindex(ifname)) == 0) 
	{
	  perror("if_nametoindex");
	  return -1;
	}
      if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) 
	{
	  perror("sysctl");
	  return -1;
	}
      if ((ifbuf = calloc(1, len)) == NULL)
	{
	  perror("calloc");
	  return -1;
	}
      if (sysctl(mib, 6, ifbuf, &len, NULL, 0) < 0) 
	{
	  perror("sysctl2");
	  return -1;
	}
      ifm = (struct if_msghdr *) ifbuf;
      sdl = (struct sockaddr_dl *) (ifm + 1);

      /* set network interface */
      ifp = (struct sockaddr_dl *) (dst + 1);
      bcopy(sdl, ifp, sizeof(struct sockaddr_dl));
      ifp->sdl_len = sizeof(struct sockaddr_dl);
    }

  if ((sockfd = socket(PF_ROUTE, SOCK_RAW, 0)) < 0)
    {
      perror("socket");
      return -1;
    }
  if (write(sockfd, rtm, rtm->rtm_msglen) < 0)
    {
      perror("write");
      //return -1;
    }
  else
    {
      strncpy(dstaddr, "", sizeof(dstaddr));
      strncpy(gateaddr, "", sizeof(gateaddr));
      strncpy(maskaddr, "", sizeof(maskaddr));
      strncpy(dstaddr, inet_ntoa(dst->sin_addr), sizeof(dstaddr));
      if (gaddr != NULL)
	strncpy(gateaddr, inet_ntoa(gate->sin_addr), sizeof(gateaddr));
      if (maddr != NULL)
	strncpy(maskaddr, inet_ntoa(mask->sin_addr), sizeof(maskaddr));
      fprintf(stderr, "\troute %s dst:%s gate:%s mask:%s ifp:%s\n",
	      rta_cmd, dstaddr, gateaddr, maskaddr, ifname);


/* A chunk of lines like this: */
	
/*  strncpy(dstaddr, "", sizeof(dstaddr));                                   */
/*  strncpy(gateaddr, "", sizeof(gateaddr));                                 */
/*  strncpy(maskaddr, "", sizeof(maskaddr));                                 */
/*  strncpy(dstaddr, inet_ntoa(dst->sin_addr), sizeof(dstaddr));             */
/*  if (gaddr != NULL)                                                       */
/*    strncpy(gateaddr, inet_ntoa(gate->sin_addr),                     */
/* 	   sizeof(gateaddr));                                               */
/*  if (maddr != NULL)                                                       */
/*    strncpy(maskaddr, inet_ntoa(mask->sin_addr),                     */
/* 	   sizeof(maskaddr));                                               */
/*  fprintf(stderr, "\troute %s dst:%s gate:%s mask:%s ifp:%s\n",            */
/* 	 rta_cmd, dstaddr, gateaddr, maskaddr, ifname);                   */
 
/* can be rewritten as: */
  
/*   fprintf(stderr, "\troute %s dst:%s gate:%s ", rta_cmd, dstaddr,         */
/* 	  (gaddr != NULL) : inet_ntoa(gate->sin_addr) ? "");                 */
/*  fprintf(stderr, "mask:%s ifp:%s\n",                                      */
/* 	 (maddr != NULL) : inet_ntoa(mask->sin_addr) ? "", ifname);          */

    }
  
#ifdef RTCTL_PRINT_RESPONSE
  fprintf(stderr, "---print response\n");
  do
    {
      n = read(sockfd, rtm, BUFLEN);
    }
  while (rtm->rtm_seq != rtm_seq || rtm->rtm_pid != pid);

  /* handle response */
  rtm = (struct rt_msghdr *) buf;
  sa = (struct sockaddr *) (rtm + 1);
  get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
  if ((sa = rti_info[RTAX_DST]) != NULL)
    fprintf(stderr, "dest: %s\n", sock_ntop_host(sa, sa->sa_len));
  if ((sa = rti_info[RTAX_GATEWAY]) != NULL)
    fprintf(stderr, "gateway: %s\n", sock_ntop_host(sa, sa->sa_len));
  if ((sa = rti_info[RTAX_NETMASK]) != NULL)
    fprintf(stderr, "netmask: %s\n", sock_masktop(sa, sa->sa_len));
  if ((sa = rti_info[RTAX_GENMASK]) != NULL)
    fprintf(stderr, "genmask: %s\n", sock_masktop(sa, sa->sa_len));
  if ((sa = rti_info[RTAX_IFP]) != NULL)
    fprintf(stderr, "ifp: len:%d fami:%d data:%s\n", sa->sa_len, 
	    sa->sa_family, sa->sa_data);
  if ((sa = rti_info[RTAX_IFA]) != NULL)
    fprintf(stderr, "ifa: len:%d fami:%d data:%s\n", sa->sa_len, 
	    sa->sa_family, sa->sa_data);
  if ((sa = rti_info[RTAX_AUTHOR]) != NULL)
    fprintf(stderr, "author: len:%d fami:%d data:%s\n", sa->sa_len, 
	    sa->sa_family, sa->sa_data);
  if ((sa = rti_info[RTAX_BRD]) != NULL)
    fprintf(stderr, "brd: len:%d fami:%d data:%s\n", sa->sa_len, 
	    sa->sa_family, sa->sa_data);
#endif

  free(buf);
  if (flag & RTCTL_IF)
    free(ifbuf);
  return 0;
}
Exemplo n.º 3
0
int getrt(char *ipaddr)
{
  int sockfd;
  char *buf;
  pid_t pid;
  ssize_t n;
  struct rt_msghdr *rtm;
  struct sockaddr *sa, *rti_info[RTAX_MAX];
  struct sockaddr_in *sin;

  if (ipaddr == NULL)
    {
      fprintf(stderr, "getrt: IP address.\n");
      return -1;
    }
  if ((sockfd = socket(AF_ROUTE, SOCK_RAW, 0)) < 0)
    {
      perror("socket");
      return -1;
    }
  buf = calloc(1, BUFLEN);
  rtm = (struct rt_msghdr *) buf;
  rtm->rtm_msglen = sizeof(struct rt_msghdr) + sizeof(struct sockaddr_in);
  rtm->rtm_version = RTM_VERSION;
  rtm->rtm_type = RTM_GET;
  rtm->rtm_addrs = RTA_DST;
  rtm->rtm_pid = pid = getpid();
  rtm->rtm_seq = SEQ;
  sin = (struct sockaddr_in *) (rtm + 1);
  sin->sin_len = sizeof(struct sockaddr_in);
  sin->sin_family = AF_INET;
  inet_pton(AF_INET, ipaddr, &sin->sin_addr);
  if (write(sockfd, rtm, rtm->rtm_msglen) < 0)
    {
      perror("write");
      exit(1);
    }
  do
    {
      n = read(sockfd, rtm, BUFLEN);
    }
  while (rtm->rtm_type != RTM_GET || rtm->rtm_seq != SEQ ||
	 rtm->rtm_pid != pid);

  /* handle response */
  rtm = (struct rt_msghdr *) buf;
  sa = (struct sockaddr *) (rtm + 1);
  get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
  if ((sa = rti_info[RTAX_DST]) != NULL)
    fprintf(stderr, "dest: %s\n", sock_ntop_host(sa, sa->sa_len));
  if ((sa = rti_info[RTAX_GATEWAY]) != NULL)
    fprintf(stderr, "gateway: %s\n", sock_ntop_host(sa, sa->sa_len));
  if ((sa = rti_info[RTAX_NETMASK]) != NULL)
    fprintf(stderr, "netmask: %s\n", sock_masktop(sa, sa->sa_len));
  if ((sa = rti_info[RTAX_GENMASK]) != NULL)
    fprintf(stderr, "genmask: %s\n", sock_masktop(sa, sa->sa_len));
  if ((sa = rti_info[RTAX_IFP]) != NULL)
    fprintf(stderr, "ifp: len:%d fami:%d data:%s\n", sa->sa_len, 
	    sa->sa_family, sa->sa_data);
  if ((sa = rti_info[RTAX_IFA]) != NULL)
    fprintf(stderr, "ifa: len:%d fami:%d data:%s\n", sa->sa_len, 
	    sa->sa_family, sa->sa_data);
  return 0;
}